使用线程在后台计算值

时间:2013-05-25 20:59:28

标签: c# multithreading task-parallel-library backgroundworker

我正在开发一个从远程计算机查询信息的程序。 WMI,注册表等我大部分都完成了,但没有线程,它运行得很慢。 (我假设它正在等待远程机器对每个请求的响应,然后再转到下一个请求。)

我已经阅读了不同的线程方法。 Thread类,BackgroundWorker类,Task类。我可以毫无问题地对所有查询进行处理,但是将所有信息都返回给主线程,以便它可以在主XAML窗口上格式化并显示RichTextBoxs中的信息。我一直得到错误,我无法访问变量,因为它们被其他线程等使用。

有人能给我一些关于如何管理/返回由其他线程计算/检索的变量的见解吗?我已经观看了很多视频并阅读了几篇关于线程的文章,但我找不到任何真正解释线程如何实际工作的内容,以及我应该知道什么时候能够并且无法从不同的线程访问变量等等。

2 个答案:

答案 0 :(得分:2)

线程是硬件的低级抽象,而Tasks提供类似的异步工作,但也允许返回结果,异常管理等。默认情况下,在Windows UI中,除非您在创建的线程上,否则无法修改UI元素它。 BackgroundWorker类是一个较旧的帮助程序类,可帮助您将结果封送回UI线程。

任务提供了一种更直接的方法来解决这个问题。在任务中执行工作程序代码,然后将更新UI的代码放在任务的后续部分中。诀窍是告诉延续在原始UI线程上运行,即UI的同步上下文。否则它将默认为先前的Task的上下文(默认情况下是线程池)

以下示例将DoWork()方法作为Task执行,然后使用Task的结果更新UI上的TextBlock。由于从UI调用Button_Click,因此其上下文是UI线程。我们只是将该上下文传递给ContinueWith()方法,以在该上下文中执行延续代码。

private void Button_Click(object sender, RoutedEventArgs e)
{
    var t = Task.Run(() => DoWork());

    t.ContinueWith(
        // take the result of the Task and update the UI
        completedTask => Output.Text = completedTask.Result.ToString()
        // tell the Task Continuation to run on the original UI context
        , TaskScheduler.FromCurrentSynchronizationContext()
        );
}

private int DoWork()
{
    return 1;
}

答案 1 :(得分:0)

这是一个标准的Windows UI问题(WinForms,XAML) - 数据来自另一个线程而不是UI线程。您可以阅读有关如何避免问题的问题WinForms - in this MSDN articleWPF XAML in this article。 .NET 4.x中的(不再那么新)任务并行库提供了一个非常好的简单同步上下文。您可以在此处阅读如何使用它:Task Synchronisation Context

还有新的async/await概念,但我还没有使用它,所以我不能说它。

线程和任务(ing)在后台是两个不同的东西,但IMHO任务足以进行简单的异步操作。我发现该库非常易于使用,主要是因为流畅的API和同步上下文支持。有关Task Parallel Library can be found here.

的更多信息