加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – Windows操作系统中(软实时)时序要求的限制

发布时间:2020-12-15 22:06:08 所属栏目:百科 来源:网络整理
导读:在我工作的公司中,我们构建的机器由运行在 Windows操作系统上的软件控制. C#应用程序与总线控制器通信(通过DLL).总线控制器的运行时间为15ms.这意味着,我们可以从总线控制器获得心跳15ms的系统中实际传感器的更新(这是实时的). 现在,这些机器正在发展成为下
在我工作的公司中,我们构建的机器由运行在 Windows操作系统上的软件控制. C#应用程序与总线控制器通信(通过DLL).总线控制器的运行时间为15ms.这意味着,我们可以从总线控制器获得心跳15ms的系统中实际传感器的更新(这是实时的).

现在,这些机器正在发展成为下一代,我们得到一个新的总线控制器,运行时间为1毫秒.由于每个人都意识到Windows不是实时操作系统,因此问题出现了:我们应该将软件的控制部分移动到实时应用程序(在实时操作系统上,例如(软)PLC).

如果我们留在Windows平台上,我们就没有保证响应能力.这本身不一定是个问题;如果我们错过了几个总线周期(有一些hickup),机器只会产生稍慢的速度(这是可以接受的).

令我担心的部分是主机控制线程之间的线程同步,以及我们从实时控制器接收的更新(每毫秒).

在哪里可以了解更多关于Windows / .NET C#在毫秒级下线程同步路径时的行为?我知道,例如Thread.Sleep(1)最多可能需要15毫秒,因为Windows正在抢占其他任务,那么当我每隔ms使用Monitor.PulseAll同步两个线程时,这是如何反映出来的?我可以期待同样不可预测的行为吗?当我在Windows应用程序中进入1ms的软实时要求时,是否会遇到麻烦?

我希望在线程的这些方面有经验的人可以对此有所了解.如果我需要澄清更多,一定要拍摄.

解决方法

您的场景听起来像是信息亭模式/专用应用程序的候选者.

In the company I work for we build machines which are controlled by software running on Windows OS.

如果是这样,您可以对机器进行装配,以便您的低延迟I / O线程可以在专用内核上运行,并最大化线程和进程优先级.此外,确保机器具有足够的内核来处理缓冲线程以及处理传输中数据的任何其他线程.如果可能,缓冲区应该预先分配内存以避免垃圾收集瓶颈.

@ Aron的例子适用于数据完整性可能在某种程度上受到损害的情况.在音频中,由于多种原因,在录制期间延迟很重要,但对于纯播放,数据丢失在某种程度上是可接受的.我假设这不是你的选择.

当然,Windows并非设计为实时操作系统,但如果您将其用于专用应用程序,则可以控制它的各个方面,并可以关闭所有不相关的服务和后台进程.

通过测量功率补偿响应时间,我已经在编写软件以监控UPS单元处理功率波动的能力方面取得了相当大的成功(免责声明:不是出于商业目的).由于每个样本测量的数据非常小,因此GC没有问题,我们为缓冲区循环预先分配的内存块.

一些微观优化派上用场:

>使用不可变结构来轮询I / O数据.
>优化数据结构以适应内存分配.
>优化处理算法以最大限度地减少CPU缓存未命中.
>使用优化的缓冲区类来保存传输中的数据.
>使用Monitor和Interlocked类进行同步.
>使用带有(void *)的不安全代码,以各种方式轻松访问缓冲区数组,以减少处理时间.最少使用Marshal和Buffer.BlockCopy.

最后,您可以使用DDK方式编写一个小驱动程序.虽然偏离主题,但DFMirage是视频驱动程序的一个很好的例子,它提供基于事件和轮询的差异屏幕捕获模型,以便消费者应用程序可以根据系统负载即时选择.

至于Thread.Sleep,考虑到您的能耗边界,您可以尽可能少地使用它.通过冗余进程,Thread.Sleep(1)不应该像你想象的那么糟糕.尝试以下方法,看看你得到了什么.请注意,这已在SO编辑器中编码,因此我可能犯了错误.

Thread.CurrentThread.Priority = ThreadPriority.Highest;
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime;

var ticks = 0L;
var iteration = 0D;
var timer = new Stopwatch();

do
{
    iteration++;
    timer.Restart();
    Thread.Sleep(1);
    timer.Stop();
    ticks += timer.Elapsed.Ticks;

    if (Console.KeyAvailable) { if (Console.ReadKey(true).Key == ConsoleKey.Escape) { break; } }

    Console.WriteLine("Elapsed (ms): Last Iteration = {0:N2},Average = {1:N2}.",timer.Elapsed.TotalMilliseconds,TimeSpan.FromTicks((long) (ticks / iteration)).TotalMilliseconds);
}
while (true);

Console.WriteLine();
Console.WriteLine();
Console.Write("Press any key to continue...");
Console.ReadKey(true);

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读