用于处理从另一个线程触发的事件的模式

时间:2012-08-02 23:39:25

标签: c# .net multithreading event-handling

假设我有两个主题。在一个帖子中,我正在执行一系列工作。在另一个线程上,我正在等待用户输入来控制这些作业(即,跳到下一个作业)。例如(伪C#):

public class Worker {

    public List<Job> Jobs { get; set; }

    public Worker(Controller anotherThread) {
        anotherThread.SkipJobRequested += OnSkipJobRequested;
    }

    public DoWork() {
        foreach (Job job in Jobs) {
            // Do various work...
        }
    }

    // Event that fires on Controller thread
    public void OnSkipJobRequsted(Object sender, EventArgs args) {
        // Somehow skip to the next job
    }
}

我不确定我应该如何处理跳到下一份工作。我遇到的一种可能性是在请求跳过时设置一个实例变量(如IsSkipRequested),并在DoWork()内的各个接合点进行检查。

是否存在可用于处理此事件的其他模式?

2 个答案:

答案 0 :(得分:3)

另一种模式是.Net类BackgroundWorker,它似乎应该适合您的目的。您可以将 Job 作为 BackgroundWorker 的子类,然后循环显示。区别在于 BackgroundWorker 不了解您的UI线程,只知道是否已请求取消。

在此模式中,UI线程将调用 CancelAsync ,然后您的 DoWork 方法将以方便的时间间隔检查 CancellationPending 以决定是否继续。您可以为 RunWorkerCompleted 事件处理程序中的下一个作业调用 RunWorkerAsync

答案 1 :(得分:1)

如果您将List<Jobs> Queue<Jobs>作为 _currentJob = Jobs.DeQueue(); Task.Factory.StartNew(() => {_currentJob.execute();}, () => { //On task completion logic ExecuteNextJobFromQueue(); } ,而不是DoWork执行foreach维护您对象中当前正在执行的作业,那么另一个建议就是(并且您已经提到了上述内容),您可以简单地出列每个项目准备好处理时。

任务并行库允许您指定取消令牌(尽管您可能必须将其传递给作业执行代码,并在那里处理取消),您可以在按下跳过时调用RequestCancellation,并启动队列中的下一个工作。此外,在启动新任务时,您可以指定要在完成时执行的操作,这将允许您将任务链接到一个顺序,并在需要时跳过任务。以下是没有取消令牌的示例:

{{1}}

请注意,如果Job执行多个任务而不是一个大的阻塞任务,这种方法可能会更有效,因为您需要在作业执行期间检查取消。