C# 如何在多线程应用程序中实现顺序阻塞行为

C# how to achive sequential blocking behavior in multithread application

我正在编写一个应模拟 PLC 行为的应用程序。这意味着我必须 运行 多个线程以确保一次只有一个线程处于活动状态,而所有其他线程都被挂起。 例如:

最高优先级是在任务被再次调用之前完成,否则我必须做出反应,所以应该阻塞的线程不要运行到某个点,否则多核处理会详细说明代码,只等待通过结果。

我读了几篇文章,了解到 Thread.suspend 不被推荐,信号量或监视器操作意味着代码一直执行到代码中的特定固定点,而我必须暂停线程恰好在当另一个线程(具有更高 "priority")被调用时,执行已经到来。

我也查看了优先级设置,但它似乎不是 100% 相关,因为系统可以覆盖优先级。

是否有正确或至少可靠的方法来编写阻塞机制?

希望我不会误解你的问题:)

您的问题的一种可能是使用并发队列: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);

在此基础上,您可以管理您提出的特殊要求。

希望这是您要搜索的内容。

我认为您根本不需要为 Thread 增加负担。相反,您可以将 Task 与优先级 TaskScheduler 一起使用(编写或通过谷歌搜索并不难找到)。

这使得代码很容易编写,例如最高优先级的线程可能是这样的:

while (!cancellationRequested)
{
  var repeatTask = Task.Delay(130);

  // Do your high priority work      

  await repeatTask;
}

您的其他任务将具有类似的基本布局,但它们在任务调度程序中的优先级较低(这通常由任务调度程序处理,每个任务优先级都有一个单独的队列)。偶尔,他们可以检查是否有更高优先级的任务,如果有,他们可以做await Task.Yield();。事实上,在你的情况下,你似乎甚至不需要真正的队列——这让这变得更容易,甚至更好,让你真正有效地使用 Task.Yield

最终结果是所有三个周期性任务都在单个线程上高效 运行(如果它们都在等待,甚至根本没有线程)。

当然,这确实依赖于协作式多任务处理。像 Windows 上的抢占一样处理完全实时是不可能的 - 部分抢占解决方案往往充满问题。如果您可以控制任务中花费的大部分时间(并使用异步 I/O 卸载任何其他工作),合作解决方案实际上效率更高,并且可以减少延迟(尽管它真的应该没什么大不了的)。