I’m trying to find a way to schedule Tasks to run in sequence. The solution I came up so far with is posted below, but I have a suspicion that it can be done in a much easier / more efficient way.
public class SequentialTaskRunner
{
private ISet<Task> runningTasks = new HashSet<Task>();
public void Run(Task task)
{
lock (runningTasks)
{
var tasksToAwait = runningTasks.ToArray();
// create a task that waits for the currently running tasks
var waitingTask = Task.Factory.StartNew(() =>
{
Task.WaitAll(tasksToAwait);
});
// make sure the task gets removed from the running tasks on completion
task.ContinueWith((antecedent2) =>
{
lock (runningTasks)
{
runningTasks.Remove(task);
}
});
// prepend the waiting task
waitingTask.ContinueWith((antecedent) => task.Start());
runningTasks.Add(task);
}
}
}
I want to use this for enqueueing tasks dealing with com-port connections, to prevent them from getting in each others way.
The situation is as follows: I’m working with an rfid device. There’s 2 drivers in play. 1 for reading / writing. Another one that can scan the available com ports on request to find an(other) reader. Sometimes, a port scan will be done using the reader driver, to restore a connection. It’s exactly these 2 ‘port scanning’ tasks that I do not want to co-occur.
I hope this clarifies how I got into the situation of wanting 2 tasks not to run at the same time. Now, there may be another way out, avoiding having to answer this question. But I’m still very curious what a good solution would be 🙂
(Entire previous post stricken per comments).
My new understanding is you have 3 types of tasks.
You’d like these three to be as parallel as possible, but you’d also like the Reader, if it so chooses to jump into a port-scanning Reconnect, to not do so while a Port Scanner is alive. One way to tackle this situation is with a Semaphore. Semaphores control access to a limited number of resources.
In your case, you have a limited number (in fact just 1) of resources (“port scanning”) available. In this instance we could elect to use a simpler
AutoResetEvent. However, I feel aSemaphoremay actually reduce confusion.The Port Scanner task would use the same
Semaphore, ensuring only 1 thread executes a port scan at a time.