1

我有一个关于线程的问题。

我有一个 WPF 应用程序,它应该显示一些查询的状态。为此,我创建了一个类,它在多个线程(后台工作人员)中运行多个查询。我还创建了一个事件,因此我可以在查询运行时做出反应。

    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 在同一个线程中吗?我该如何解决我的问题?

4

3 回答 3

5

不会。
大多数非 UI 组件会在非 UI 线程(通常是 ThreadPool 线程)中引发回调

您可以调用Dispactcher.BeginInvoke在 UI 线程上运行代码:

Dispactcher.BeginInvoke(new Action(delegate {
    ...
}));
于 2012-10-31T14:25:52.377 回答
2

不,该事件不会在 UI 线程上执行。

虽然它很容易解决,但您应该调用与 UI 线程上的 GUI 元素交互的代码:

private void sql_QueryCompleted(QueryResult qr)
{
    Dispatcher.BeginInvoke(new Action(() => { 
        lstStatus.Items.Clear();
        lstStatus.Items.Add(qr.RuntimeTotal);
        //... and some more...
    });
}
于 2012-10-31T14:27:36.663 回答
1

Dispatcher.BeginInvoke 总是有助于从其他线程更新控件。此外,如果您使用 Backgroundworker 类并从 DoWork 引发事件,则会在 DoWork 线程上引发事件处理程序。如果您从 Backgroundworker 的 WorkCompleted 事件中引发事件,它将在您启动 Backgroundworker 的线程上引发,该线程可以是您的 UI 线程(此处不需要 Dispatcher)。Backgroundworker.ProgressChanged 事件也是如此。

于 2012-11-01T20:15:04.340 回答