我对线程有疑问。
我有一个WPF应用程序,它应该显示一些查询的状态。为此,我创建了一个类,它在多个线程(backgroundworker)中运行多个查询。我还创建了一个事件,所以我可以在查询运行时做出反应。
private void cmdStart(object sender, RoutedEventArgs e)
{
QuerySetup qs = new QuerySetup();
//Filling qs with some data
//...
SqlProxy sql = new SqlProxy();
sql.QueryCompleted += new SqlProxy.QueryCompletedEventHandler(sql_QueryCompleted);
//Starts the backgroundworker
sql.RunSQL(qs);
}
private void sql_QueryCompleted(QueryResult qr)
{
lstStatus.Items.Clear();
lstStatus.Items.Add(qr.RuntimeTotal);
//... and some more...
}
现在我收到一条错误消息,告诉我,我无法访问lstStatus,因为它由不同的线程拥有。
但为什么呢?事件不应该与GUI在同一个线程中吗?我怎样才能解决我的问题?
答案 0 :(得分:5)
没有。
大多数非UI组件都会在非UI线程(通常是ThreadPool线程)中引发回调
您可以调用Dispactcher.BeginInvoke
在UI线程上运行代码:
Dispactcher.BeginInvoke(new Action(delegate {
...
}));
答案 1 :(得分:1)
不,该事件不会在UI线程上执行。
虽然很容易解决,但您必须调用与UI线程上的GUI元素交互的代码:
private void sql_QueryCompleted(QueryResult qr)
{
Dispatcher.BeginInvoke(new Action(() => {
lstStatus.Items.Clear();
lstStatus.Items.Add(qr.RuntimeTotal);
//... and some more...
});
}
答案 2 :(得分:1)
Dispatcher.BeginInvoke总是有助于更新来自其他线程的控件。 此外,如果您正在使用Backgroundworker类并从DoWork引发事件,则会在DoWork线程上引发事件处理程序。 如果你从Backgroundworker的WorkCompleted事件中引发事件,它将在你启动Backgroundworker的线程上引发,它可以是你的UI线程(这里不需要Dispatcher)。 Backgroundworker.ProgressChanged事件也是如此。