Reputation: 6016
Suppose I have two threads. On one thread, I'm performing a sequence of jobs. On the other thread I'm waiting for user input to control those jobs (i.e., skip to the next job). For example (pseudo-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
}
}
I'm uncertain how I should handle skipping to the next job. One possibility that occurs to me would be to have an instance variable (like, IsSkipRequested
) that I set when a skip is requested, and check it at various junctures within DoWork()
.
Do any other patterns exist that I could use to handle this event?
Upvotes: 2
Views: 616
Reputation: 4319
Another suggestion would be (and you have mentioned this above) if you made List<Jobs>
a Queue<Jobs>
, and rather than DoWork performing a foreach maintained the current executing job in your object, you could simply dequeue each item when ready for processing.
The task parallel library allows you to specify a cancellation token (although you would probably have to pass this to your job execution code, and handle cancellation in there), which you can call RequestCancellation on when skip is pressed, and start the next job from the queue. Additionally, when firing off a new task you can specify an action to perform on completion, this would allow you to chain your tasks together into a sequential order and skip tasks when required. Below is an example without a cancellation token:
_currentJob = Jobs.DeQueue();
Task.Factory.StartNew(() => {_currentJob.execute();},
() =>
{
//On task completion logic
ExecuteNextJobFromQueue();
}
Be aware that this approach would probably work best if Job is performing multiple tasks and not one big blocking task as you would need to check for cancellation during job execution.
Upvotes: 1
Reputation: 102753
Another pattern is the .Net class BackgroundWorker, which seems like it should suit your purpose. You could make Job a subclass of BackgroundWorker, and cycle through. The difference is that BackgroundWorker doesn't know about your UI thread, only whether cancellation has been requested.
In this pattern the UI thread would call CancelAsync, then your DoWork method would check the CancellationPending at convenient intervals to decide whether or not to proceed. You would call RunWorkerAsync for the next job inside the RunWorkerCompleted event handler.
Upvotes: 3