.NET:用于同步长时间运行任务的机制

时间:2010-02-20 10:29:32

标签: c# multithreading user-interface asynchronous synchronization

问题描述:您编写的库中包含一些可能需要很长时间才能完成的算法/任务,原因有多种:计算,文件系统,网络通信等。您希望能够到:

  1. 发送有关任务的进度信息(进度,活动记录等)
  2. 如果设置了某些外部信号或属性,可以在完成之前中止任务。
  3. 我为此实现了一个框架,但这要求所有这些任务都必须引用包含此框架的程序集。

    我的问题:在.NET框架(3.5或更低版本)中是否存在针对上述问题的内置机制?

    我知道我可以使用事件,但这意味着长时间运行的任务必须暴露这些事件,我认为这是一个开销。理想情况下,我希望有一个隐藏多线程问题的框架,并且依赖注入友好,但不依赖于额外的自定义程序集,也不会污染原始接口。

    我希望我能够很好地描述这个问题。如果没有,我可以从我自己的框架发布一些接口样本。

    更新:好的,我认为我的问题描述需要一点澄清:)。当我说“长期运行”时,我并不是说工作流程意义上的“长”。我正在开发一个WinForms地图应用程序,它可以处理各种各样的事情,比如生成relief contours。要做到这一点,首先必须从FTP服务器下载高程数据文件,解压缩然后执行一些计算。我很久以前就为此编写了代码,但是为了使它更适合GUI,我必须改进各种检查 - 例如,检测用户是否点击了中止按钮并停止了进程。 / p>

    基本上我的关注点是:如何编写一个稍后(如果有的话)可以在GUI环境中使用的代码,在这种情况下,您不能简单地在主GUI线程中运行所有内容并冻结整个应用程序。 挑战在于找到一种方法,使您的代码适合GUI目的,而无需将其绑定到特定的GUI平台。

4 个答案:

答案 0 :(得分:6)

这听起来很像Windows Workflow Foundation

答案 1 :(得分:2)

看看传奇模式。它没有内置到框架中,但可以实现。另外,NServiceBus和MassTransit都有此实现。 Arnon RGO在他的书中有一个草稿(将会完成),描述它here

根据我的经验,使用NServiceBus比WF简单得多,而且功能也更强大(虽然我没有看过WF 4,因为微软已经认识到WF 4的失败,所以所有描述都是WF的近乎彻底的改造。这一点)。

即使你不想要像NServiceBus或MassTransit这样的框架,这个模式本身也值得一看,因为它与你所描述的内容非常接近。

答案 2 :(得分:1)

这取决于您的系统有多复杂。对于相对简单的问题,您可以很好地使用.NET 2.0中的BackgroundWorker class。它支持使用OnProgressChanged事件报告操作的进度,并且还支持使用CancelAsync方法取消后台任务。

该类由事件控制,但由于这已经是该类的一部分,我认为这不是任何开销:

var bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RunWorkerCompleted);
bw.ProgressChanged += new ProgressChangedEventHandler(ProgressChanged);
  • 执行DoWork方法以运行后台任务(它可以通过调用bw.ReportProgress来报告进度,并使用bw.CancellationPending检查待处理的取消。

    < / LI>
  • 操作完成后,在GUI线程上执行RunWorkerCompleted方法(这为您提供了一种很好的同步方式,而不必担心并发)

  • 只要您的ProgressChanged方法报告某些进度更改,就会触发DoWork事件。

对于更简单的问题,我相信您可以将您的任务表示为后台工作人员。

答案 3 :(得分:0)

我更喜欢使用回调方法在需要更新某些内容或进度时发出UI线程的信号。您可以传递复杂对象,并且回调可以返回一个值,以防它需要发出工作线程的信号。而且你可以根据工人的需要来定义多个回调。