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



假设我有两个线程。在一个线程上,我正在执行一系列作业。在另一个线程上,我正在等待用户输入来控制这些作业(即,跳到下一个作业)。例如(伪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()内的各个节点对其进行检查。

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

另一种模式是.Net类BackgroundWorker,它似乎适合您的目的。您可以使Job成为BackgroundWorker的子类,然后循环使用。不同的是BackgroundWorker不知道您的UI线程,只知道是否请求了取消。

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

另一个建议是(您已经在上面提到了这一点)如果您将List<Jobs>设置为Queue<Jobs>,并且DoWork不执行foreach来维护对象中的当前执行作业,而是可以在准备好处理时将每个项目排成队列。

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

        _currentJob = Jobs.DeQueue();
        Task.Factory.StartNew(() => {_currentJob.execute();}, 
        () => 
        {
            //On task completion logic
            ExecuteNextJobFromQueue();                              
        }

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

相关内容

  • 没有找到相关文章

最新更新