【问题标题】:Execute task in background in WPF application在 WPF 应用程序的后台执行任务
【发布时间】:2014-01-24 07:12:41
【问题描述】:

例子

private void Start(object sender, RoutedEventArgs e)
{
    int progress = 0;
    for (;;)
    {
        System.Threading.Thread.Sleep(1);
        progress++;
        Logger.Info(progress);
    }
}

如果我想要Start() ,推荐的方法是什么(TAP 或 TPL 或 BackgroundWorker 或 Dispatcher 或其他)

  1. 不阻塞 UI 线程
  2. 提供进度报告
  3. 可以取消
  4. 支持多线程

【问题讨论】:

标签: c# wpf multithreading task-parallel-library tap


【解决方案1】:

对于 .NET 4.5(或 .NET 4.0 + Microsoft.Bcl.Async),最好的方法是使用基于 Task 的 API 和 async/await。它允许使用方便的(伪)顺序代码工作流程并具有结构化的异常处理。

例子:

private async void Start(object sender, RoutedEventArgs e)
{
    try
    {
        await Task.Run(() =>
        {
            int progress = 0;
            for (; ; )
            {
                System.Threading.Thread.Sleep(1);
                progress++;
                Logger.Info(progress);
            }
        });
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

更多阅读:

How to execute task in the WPF background while able to provide report and allow cancellation?

Async in 4.5: Enabling Progress and Cancellation in Async APIs.

Async and Await.

Async/Await FAQ.

【讨论】:

  • @publicENEMY,基于Task 的 API 使 BackgroundWorker 过时,请阅读:Task.Run vs BackgroundWorkerTask.Run 使用 ThreadPool 线程来运行您的任务,所以是的,它当然支持多线程和多核。有一些学习曲线,但非常值得。
  • @publicENEMY 不用担心多核。操作系统将线程分配给内核(称为处理器亲和性)并尽可能使用所有内核!任何异步编程方法都使用Threads,如果你深入挖掘的话。
  • @publicENEMY, BackgroundWorker 仍然可以成功使用,像ThreadPool.QueueUserWorkItemnew Thread() 这样的低级线程API 也可以完成工作。虽然,像 Task/async/await, IMO 那样编写代码不会那么愉快。
  • +1 用于添加的资源 一个我发现有用的网址。 msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx
  • @Legends,我在另一个答案here中有一个完整的例子。
【解决方案2】:

最好的方法是使用BackgroundWorker

我指出这一点的原因是它专门设计用于在后台处理工作,同时保持 UI 线程可用和响应。它还内置了Progress通知并支持Cancellation

我建议查看 BackgroundWorker 的几个示例。

现在,当您开始研究后台工作人员时,您必须深入研究一点Cancellation。设置后台工作人员的取消属性不会取消后台工作人员,这只会为您的运行方法引发一个标志,以定期询问并优雅地停止处理。

这是我不久前关于取消后台工作人员https://stackoverflow.com/a/20941072/1397504的帖子之一

最后。异步并不意味着多核甚至多线程。 (WIKI)

【讨论】:

  • 您对 BackgroundWorker 支持取消和进度报告是正确的。谢谢。
【解决方案3】:

您可以使用 BackgroundWorker 类在 WPF 中的单独线程上执行操作。

检查这个例子How to use WPF Background Worker

并在此处阅读 MSDN 上的课程 http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

【讨论】:

  • 我完全忘记了 BackgroundWorker。我的印象是 BackgroundWorker 是 Winform 和 WPF 等效的是 Dispatcher 类。顺便说一句,AFAIK BackgroundWorker 不支持多线程。如果我错了,请纠正我。
  • “创建多线程应用程序最可靠的方法是使用 BackgroundWorker 组件。此类管理一个单独的线程,专门用于处理您指定的方法。”来自msdn.microsoft.com/en-us/library/ck8bc5c6.aspx
  • @publicENEMY 后台工作者是一个帮助类,用于运行异步操作和报告进度您可以在 winforms 和 wpf 中使用它,因为SynchronizationContext 机制对两者都是一致的。每个 winforms 对象都包含一个 WindowsFormsSynchronizationContext 实例(允许访问 UI 线程),但 WPF 将 实际消息泵 公开为 Dispatcher/ 这包含一个 DispatcherSynchronizationContext
  • @SQL.NETWarrior 感谢您的链接。让决定变得容易。
  • @Gusdor 谢谢。我不知道。
猜你喜欢
  • 2011-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-12
相关资源
最近更新 更多