我正在编写一个应该模拟PLC行为的应用程序。这意味着我必须运行多个线程,确保一次只有一个线程处于活动状态,所有其他线程都被挂起。 例如:
最高优先级是在再次调用任务之前完成任务,否则我必须做出反应,因此应该阻塞的线程不应该运行到某个点,否则多核处理会详细说明代码而只等待通过结果。
我阅读了几篇帖子,并了解到Thread.suspend不是推荐的,信号量或监视操作意味着代码执行直到代码中的特定和固定点,而我必须暂停线程到达执行时到达的位置调用另一个线程(具有更高的"优先级")。
我还查看了优先级设置,但它似乎没有100%相关,因为系统可以覆盖优先级。
是否有正确或至少可靠的方法来编码阻止机制?
答案 0 :(得分:1)
我希望我不会错过理解你的问题:)
您的问题的一种可能性可能是使用并发队列:https://msdn.microsoft.com/de-de/library/dd267265(v=vs.110).aspx
例如,您创建一个枚举来控制您的状态并启动队列:
private ConcurrentQueue<Action> _clientActions ;
private enum Statuskatalog
{
Idle,
Busy
};
创建一个计时器以启动并创建一个timerfunktion。
Timer _taskTimer = new Timer(ProcessPendingTasks, null, 100, 333);
private void ProcessPendingTasks(object x)
{
_status = Statuskatalog.Busy;
_taskTimer.Change(Timeout.Infinite, Timeout.Infinite);
Action currentTask;
while( _clientActions.TryDequeue( out currentTask ))
{
var task = new Task(currentTask);
task.Start();
task.Wait();
}
_status=Statuskatalog.Idle;
}
现在,您只需将任务作为代理添加到队列中:
_clientActions.Enqueue(delegate { **Your task** });
if (_status == Statuskatalog.Idle) _taskTimer.Change(0, 333);
在此基础上,您可以管理您要求的特殊要求。
希望这是,你在寻找什么。
答案 1 :(得分:1)
我认为你根本不需要给自己增加负担Thread
。相反,您可以将Task
与优先级TaskScheduler
一起使用(通过Google搜索来编写或查找并不难)。
这使代码非常容易编写,例如,最高优先级的线程可能类似于:
while (!cancellationRequested)
{
var repeatTask = Task.Delay(130);
// Do your high priority work
await repeatTask;
}
您的其他任务将具有类似的基本布局,但在任务调度程序中它们将被赋予较低的优先级(这通常由任务调度程序处理,每个任务优先级具有单独的队列)。偶尔,他们可以检查是否有更高优先级的任务,如果有,他们可以await Task.Yield();
。事实上,在你的情况下,你似乎甚至不需要真正的队列 - 这使得这更容易,甚至更好,让你真正有效地使用Task.Yield
。
最终结果是,所有三个周期性任务都只在一个线程上有效运行(如果它们都在等待,甚至根本就没有线程)。
当然,这确实依赖于合作多任务。实际上不可能像Windows上的抢先一样处理全面实时 - 部分抢占解决方案往往充满了问题。如果您控制了在任务中花费的大部分时间(并使用异步I / O卸载任何其他工作),那么协同解决方案实际上效率更高,并且可以减少延迟(尽管它确实不应该太重要了。