我正在尝试找到一种方法来安排任务按顺序运行。我到目前为止提出的解决方案发布在下面,但我怀疑它可以更简单/更有效的方式完成。
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);
}
}
}
我想使用它来排队处理com-port连接的任务,以防止它们以彼此的方式进入。
情况如下:我正在使用rfid设备。有2个司机在场。 1用于读/写。另一个可以根据请求扫描可用的COM端口以查找(其他)阅读器。有时,将使用阅读器驱动程序完成端口扫描,以恢复连接。正是这些2'端口扫描'任务我不想共同发生。
我希望这可以澄清我是如何陷入想要让两个任务不能同时运行的情况的。现在,可能还有另一条出路,避免回答这个问题。但我仍然非常好奇一个好的解决方案是什么:)
答案 0 :(得分:4)
(每条评论完整的上一篇文章)。
我的新理解是你有3种类型的任务。
你希望这三者尽可能并行,但是你也喜欢Reader,如果它选择跳转到端口扫描重新连接,那么在端口扫描器处于活动状态时不这样做。解决这种情况的一种方法是使用Semaphore。信号量控制对有限数量资源的访问。
在您的情况下,您可以使用有限数量(实际上只有1个)的资源(“端口扫描”)。在这种情况下,我们可以选择使用更简单的AutoResetEvent
。但是,我觉得Semaphore
实际上可能会减少混淆。
// Only 1 task may port scan at a time
Semaphore portScanResource = new Semaphore(initialCount: 1, maximumCount: 1);
// ...
// "Reader task"
var task = Task.Factory.StartNew( () =>
{
// ...
if (shouldPortScan)
{
portScanResource.WaitOne();
try
{
// do your port scan
}
finally
{
// we're done
portScanResource.Release();
}
}
});
端口扫描程序任务将使用相同的Semaphore
,确保一次只有一个线程执行端口扫描。
答案 1 :(得分:0)
如果你在C#4上,你可以ConcurrentQueue
类对你的队列是线程安全的
或查看C4中的其他Concurrent *类。并行扩展也非常方便,但是oyu需要根据需要进行调整