如何让一个类中的长时间运行的方法向C#中的调用类报告其进度?

如何让一个类中的长时间运行的方法向C#中的调用类报告其进度?,c#,.net,C#,.net,我有一个方法可以处理数千个项目,而且需要很长时间 什么是“正确”的方法,让正在执行长操作的方法在执行此操作时报告其进度 例如,如果我想让UI中的进度条显示另一个线程中某个长时间运行的方法的进度。请使用进度条 在BackgroundWorker上有几个SO问题,例如: 在这种特殊情况下,我倾向于创建一个自定义事件,并从长时间运行的流程中触发它,然后在事件处理程序中订阅要更新到事件的任何UI元素。(UI始终在主UI线程中更新)长时间运行的任务(无论是否在专用后台线程中运行)可能希望通过以下两种方

我有一个方法可以处理数千个项目,而且需要很长时间

什么是“正确”的方法,让正在执行长操作的方法在执行此操作时报告其进度

例如,如果我想让UI中的进度条显示另一个线程中某个长时间运行的方法的进度。

请使用进度条

在BackgroundWorker上有几个SO问题,例如:


在这种特殊情况下,我倾向于创建一个自定义事件,并从长时间运行的流程中触发它,然后在事件处理程序中订阅要更新到事件的任何UI元素。(UI始终在主UI线程中更新)

长时间运行的任务(无论是否在专用后台线程中运行)可能希望通过以下两种方式之一与调用者通信:

  • 报告进度(对于BackgroundWorker,这对应于调用
    BackgroundWorker.ReportProgress

  • 检查是否已请求取消(与BackgroundWorker一起,这对应于检查
    CancellationPending
    属性)

对于长时间运行的流程来说,能够以这种方式与调用方通信,而不知道或不关心它是否由后台工作人员运行,这有时是很有用的。因此,我创建了一个接口
IProgress
,该接口使用方法
ReportProgress
和属性
CancellationPending
来抽象此功能。我有一个实现这个接口的BackgroundWorker的增强版本,还有一些不使用BackgroundWorker的替代实现

例如,控制台应用程序可能在前台运行长时间运行的任务。其
IProgress.ReportProgress
的实现,例如,如果在详细模式下运行,可以使用
Console.WriteLine
。它的
IProgress.CancellationPending的实现可以检查是否按下了CTRL-C。可以从此控制台应用程序和使用BackgroundWorker的WinForms应用程序调用相同的长时间运行任务


我个人认为,在设计BackgroundWorker时,这样的抽象应该包含在.NET框架中。

仅仅更新UI不是有点浪费吗?对于拆分长时间运行的进程并使其线程化,而不是简单地从一个长时间运行的进程报告,这难道不是一个更好的解决方案吗?自定义事件有一个缺点,即它们需要被封送到订阅服务器的线程,这需要编写几行额外的代码。但是BackgroundWorker可以很好地为您处理这个问题。我怀疑仅仅在锁定的UI上有一个进度条会安抚用户,所以我认为可以安全地假设OP也需要一个单独的线程。@Aviad,@ProfK,听说过KISS吗?BackgroundWorker并不是关于长时间运行代码的所有问题的答案。很高兴看到其他人(即Tim)也意识到还有其他选择。“UI总是在主线程中更新”——这不是自动的。您需要使用Control.Invoke来更新从后台线程触发的事件处理程序中的UI元素。或者找一个后台工作人员帮你解决这个问题。