2

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

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

4

2 回答 2

3

另一种模式是 .Net 类BackgroundWorker,它似乎应该适合您的目的。你可以让Job成为BackgroundWorker的子类,然后循环。不同之处在于BackgroundWorker不知道您的 UI 线程,只知道是否已请求取消。

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

于 2012-08-03T00:14:25.353 回答
1

另一个建议是(并且您在上面已经提到过)如果您创建了List<Jobs>一个Queue<Jobs>,而不是 DoWork 执行一个 foreach 来维护您的对象中当前正在执行的作业,您可以在准备好处理时简单地将每个项目出列。

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

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

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

于 2012-08-04T09:14:25.537 回答