我继承了旧的VB6 DLL来控制工业机械。我已将其转换为C#。除了一个功能外,它运行良好:VB6版本支持"异步"模型通过计时器每秒醒来更新一些机器并更新大量数据结构和全局变量。它之所以侥幸,因为VB6实际上是单线程的,即使它可以通过排队事件来在子例程调用之间执行或通过DoEvent来模拟异步。
在C#中,我们进行了真正的异步处理,因为 System.Timers.Timer 我正在使用导致正在运行的新线程。不幸的是,这意味着当计时器线程试图操纵用户的应用程序线程也触及的项目时,我们会发生线程冲突。
警告:计时器线程操纵的数据很大且多种多样 - 数百种不同的数据结构,变量和标志在其他DLL调用中使用,所以它是仅仅制作一些关键部分来保护它是不切实际的。
理想情况下,最简单的方法是将定时器代码的工作转移到将在应用程序线程中运行的调用中,并且只是使用定时器以某种方式触发它。但是如何?
我们的这个DLL 的测试应用程序发生是一个WPF程序,所以我们可能会使用某种DispatchTimer线程在我们的测试用例中解决这个,但是我们没有理由假设用户的应用程序是基于调度程序的,因此它不是通用的解决方案。
答案 0 :(得分:0)
如果计时器每次都没有处理数据,你可以使用Monitor.TryEnter(),只需声明一个同步对象。像。的东西。
private readonly object _syncObject = new object();
.....
private void ProcessingMethod(){
if(Monitor.TryEnter(_syncObject))
{
try{
//do some processing.
}
finally{
Monitor.Exit(_syncObject);
}
}
}
如果计时器必须在每个时间间隔处理,那么您需要使用lock
语句。如果处理时间很长,您将需要编写防止计时器积压的逻辑。
我假设正在处理的对象不是在WPF上下文中创建的,或者由于某种原因你无法将上下文传递给处理方法。