0

我正在开发一个从远程计算机查询信息的程序。WMI、注册表等。我已经完成了大部分工作,但是如果没有线程,它运行速度很慢。(我假设它正在等待远程机器对每个请求的响应,然后再继续下一个请求)。

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

谁能给我一些关于如何管理/返回由其他线程计算/检索的变量的见解?我观看了许多视频并阅读了几篇关于线程的文章,但我找不到任何真正解释线程实际工作原理的文章,以及我应该如何知道何时可以和不能从不同线程访问变量, ETC。

4

2 回答 2

3

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

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

下面是一个示例,它将 DoWork() 方法作为任务执行,然后使用任务的结果更新 UI 上的 TextBlock。由于 Button_Click 是从 UI 调用的,因此它的上下文是 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;
}
于 2013-05-28T21:05:43.023 回答
0

这是一个标准的 Windows UI 问题(WinForms、XAML)——数据来自不同于 UI 线程的另一个线程。您可以在这篇 MSDN 文章中了解如何避免 WinForms 问题,在这篇文章中了解WPF XAML。.NET 4.x 中的(不再是新的)任务并行库提供了一个非常好的和简单的同步上下文。您可以在此处阅读如何使用它:任务同步上下文

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

Threading 和 Task(ing) 在后台是两个不同的东西,但是恕我直言,Tasks 对于琐碎的异步操作来说已经足够了。我发现这个库非常好用,主要是因为流畅的 API 和同步上下文支持。可以在此处找到有关任务并行库的更多信息。

于 2013-05-25T21:14:31.070 回答