C# .NET:同步长时间运行任务的机制
问题描述:您编写了一个库,其中包含一些可能需要很长时间才能完成的算法/任务,原因多种多样:计算、文件系统、网络通信等。您希望能够:C# .NET:同步长时间运行任务的机制,c#,multithreading,user-interface,asynchronous,synchronization,C#,Multithreading,User Interface,Asynchronous,Synchronization,问题描述:您编写了一个库,其中包含一些可能需要很长时间才能完成的算法/任务,原因多种多样:计算、文件系统、网络通信等。您希望能够: 发送有关任务的一些进度信息(进度、活动日志等) 如果设置了某些外部信号或属性,可以在任务完成之前中止任务 我已经为此实现了一个框架,但这要求所有此类任务都必须引用包含此框架的程序集 我的问题:对于上述问题,.NET framework(3.5或更低版本)中是否已有内置机制? 我知道我可以使用事件,但这意味着长时间运行的任务必须公开此类事件,我认为这是一种开销。理想情
因此,基本上我关心的是:如何编写一个以后(如果有的话)可以在GUI环境中使用的代码,在GUI环境中,您不能简单地运行主GUI线程中的所有内容并冻结整个应用程序挑战在于找到一种方法,使您的代码适合GUI用途,而无需将其绑定到特定的GUI平台。这听起来很像。看看saga模式。它没有内置到框架中,但可以实现。或者,NServiceBus和MassTransit都实现了这一点。阿农·尔戈(Arnon RGO)有一本书的草稿(它是否会完成)描述了它 根据我的经验,使用NServiceBus比WF简单得多,而且功能也更强大(尽管我还没有看过WF 4,所有的描述都是对WF的近乎完全的修改,因为微软已经意识到了它的缺陷)
即使您不想要像NServiceBus或MassTransit这样的框架,模式本身也很值得一看,因为它与您描述的问题空间非常接近。这取决于您的系统有多复杂。对于相对简单的问题,可以很好地使用.NET2.0中的。它支持使用
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
- 当操作完成时,
方法在GUI线程上执行(这为您提供了一种很好的同步方法,而不必担心并发性)RunWorkerCompleted
- 每当
方法报告某些进度更改时,就会触发DoWork
事件ProgressChanged
对于更简单的问题,我相信您可以将您的任务表示为后台工作人员。我更喜欢使用回调方法在某些事情完成或进度需要更新时向UI线程发出信号。您可以传递复杂对象,回调可以返回一个值,以防它需要向工作线程发送信号。您还可以根据需要员工的健谈程度定义多个回调。第一个想法\u您可以考虑使用System.Diagnostics.PerformanceCounter进行数字活动日志记录。然后,任何知道其名称的应用程序都可以读取数据。要发出中止信号,可以将EventWaitHandle与命名句柄一起使用。这两种方法都不需要dll链接,但它们需要共享的“字符串”命名。或者像@mark建议的那样走WWF路线。我希望避免“干净、无辜”的库代码与诸如等待句柄、线程和WMI等棘手的代码混为一谈;)我正在寻找这些模式的抽象(最好是通过C#接口,使其更易于测试)。WWF对于我所描述的问题来说有点过火(我已经更新了描述)。@Tomas,我已经使用BackgroundWorker来实现这些目的,但间接地是在基础架构级别。问题是,将您的任务直接表示为BackgroundWorker类意味着它将始终以异步模式运行,但情况并非如此。是的,我希望BackgroundWorker在您的情况下功能不够强大。希望它能帮助人们在未来更简单的环境中解决这类问题。