创建安全“阻塞循环”的最佳方法,该循环等待由另一个线程更改的变量

时间:2014-08-30 03:26:48

标签: c# multithreading

简而言之,我有一个用编码器控制电机的PCB(所以我可以读取它的'位置'或计数)。在我的(C#)软件中,有时我需要告诉电机移动到某个位置并在程序继续之前等待它到达那里。

我使用的是.net 3.5,所以不能使用await / async功能,我最好的选择是什么?

使用如下的循环:

while (motorPositon != motorDestination) continue;

不起作用 - 它会导致使用100%CPU的挂起循环,并且永远不会将更改注册到motorDestination。这并不让我感到惊讶,但是将可怕的Application.DoEvents()添加到循环中有助于 - 至少在一些(快速)计算机上。此外,在循环中添加Thread.Sleep(x)调用似乎可以在较慢的计算机上按预期工作。

然而,这个'修复'让我感到非常不舒服,我相信一定有更好的方法。

我曾考虑使用计时器检查motorPosition而不是循环,但这对我来说也很笨拙。

我缺少一个技巧吗?这似乎是一个常见的问题,但到目前为止我的搜索还没有产生任何特别令人满意的答案。

编辑:通过对PCB的定期轮询调用来读取/更新motorPosition(这是通过计时器完成的)。

1 个答案:

答案 0 :(得分:1)

我认为如果硬件本身可以引发你可以处理的中断,并且主线程可能在中断设置的事件上等待,那将是理想的。但听起来在你的情况下这可能是不可能的。

我会使用一个BackgroundWorker,DoWork处理程序就是这样的:

BackgroundWorker worker = sender as BackgroundWorker;
while (motorPosition != motorDestination)
{
  if (worker.CancellationPending == true)
  {
    e.Cancel = true;
    break;
  }
  Thread.Sleep(500)
}

由于线程是后台线程,因此您的主UI线程应该没问题。你不会杀死CPU,因为你的线程每秒只处理两次(如果有意义则增加睡眠)。如果需要,它支持取消。 (如果取消,你可能想告诉马达停止移动。)

然后在将在主UI线程中运行的RunWorkerCompleted处理程序中,您可以选择并执行下一步操作。