我正在通过关键字以编程方式进行Youtube搜索,并使用Youtube API执行此操作。我希望在搜索进度完成时触发事件,并将结果返回YoutubeSearchCompletedEventArgs
发送的YoutubeSearchCompleted
。
但是YoutubeSearchCompleted
中的Form.cs
中的代码会引发跨线程非法操作异常。通常,使用AsyncOperation.Post
方法时,它不能抛出InvalidOperationException
。因为我之前在下载管理器项目中使用了相同的方法并且运行良好。所以我无法理解为什么会这样。
Youtube搜索类
class YouTubeManager
{
public delegate void YoutubeSearchCompletedEventHandler(object sender, YoutubeSearchCompletedEventArgs e);
public event YoutubeSearchCompletedEventHandler YoutubeSearchCompleted;
AsyncOperation aop = AsyncOperationManager.CreateOperation(null);
List<YoutubeVideo> SearchByKeyword(string keyword)
{
List<YoutubeVideo> videos = new List<YoutubeVideo>();
//.......
//...Youtube data api search codes....
//.......
return videos;
}
public void Search(string keyword)
{
Task.Run(() =>
{
List<YoutubeVideo> list = SearchByKeyword(keyword);
aop.Post(new System.Threading.SendOrPostCallback(delegate
{
if (YoutubeSearchCompleted != null)
YoutubeSearchCompleted(this,
new YoutubeSearchCompletedEventArgs(keyword, list);
}), null);
});
}
}
Form.cs
public partial class Form1 : Form
{
YouTubeManager yam = new YouTubeManager();
public Form1()
{
InitializeComponent();
this.Load += Form1_Load;
}
void Form1_Load(object sender, EventArgs e)
{
yam.YoutubeSearchCompleted += yam_YoutubeSearchCompleted;
yam.Search("Blues");
}
void yam_YoutubeSearchCompleted(object sender, YoutubeSearchCompletedEventArgs e)
{
if (e.Videos.Count < 1) return;
textBox1.Text = e.Videos[0].Title();
}
}
在此代码中,textBox1.Text = e.Videos[0].Title();
行抛出InvalidOperationException
。我该如何解决这个问题?
注意:我不想要Invoke
方法,只需AsyncOperation
。
答案 0 :(得分:3)
问题很可能是由AsyncOperation
过早创建引起的。您可以通过以下方式检查:
if (!(aop.SynchronizationContext is WindowsFormsSynchronizationContext))
{
// Oops - we have an issue
}
为什么? AsyncOperation
在构建时存储SynchronizationContext.Current
,通常所有Control
派生类(包括Form
)在WindowsFormsSynchronizationContext
内安装Control
类构造函数。
但请设想Forgm1
是您的创业形式(例如来自Application.Run(new Form1());
的典型Main
)。从Any instance variable initializers in the derived class are executed before the base class constructor开始,在aop
变量初始化时(通过yam
字段初始值设定项),Control
类构造函数尚未运行,因此WindowsFormsSynchronizationContext
未安装,因此使用默认AsynOperation
初始化SynchronozationContext
,默认Post
通过在单独的线程上执行它来实现YouTubeManager yam;
。
修复很简单 - 不要使用初始化程序,只需定义字段
yam = new YouTubeManager();
并移动初始化
SceneKit Editor
在表单构造函数或load事件中。