C# 锁与布尔
以下是场景: 计时器每分钟调用一个方法。此方法可以通过UI(按钮)调用。我希望如果我的方法是“正在处理中”,并且被调用,它不会执行该方法两次 在我的方法中,我使用了一个简单的布尔值:C# 锁与布尔,c#,multithreading,locking,C#,Multithreading,Locking,以下是场景: 计时器每分钟调用一个方法。此方法可以通过UI(按钮)调用。我希望如果我的方法是“正在处理中”,并且被调用,它不会执行该方法两次 在我的方法中,我使用了一个简单的布尔值: private bool _isProcessing; public void JustDoIt(Action a, int interval, int times) { if (!_isProcessing) { _isProcess
private bool _isProcessing;
public void JustDoIt(Action a, int interval, int times)
{
if (!_isProcessing)
{
_isProcessing = true;
for (int i = 0; i < times; i++)
{
a();
Thread.Sleep(interval);
}
}
_isProcessing = false;
}
先例测试未通过:
Message:Moq.MockException:预期对模拟的调用正好有3次,但有4次:c=>c.Writeline(“任务完成!”)
那么,我是否使用了lock关键字?它应该是“静态”的吗
谢谢使
\u isProcessing
易失性。然后这样做:
public void JustDoIt(Action a, int interval, int times)
{
if (_isProcessing) return
_isProcessing = true;
for (int i = 0; i < times; i++)
{
a();
Thread.Sleep(interval);
}
_isProcessing = false;
}
public void JustDoIt(动作a,整数间隔,整数倍)
{
如果(_isProcessing)返回
_isProcessing=true;
for(int i=0;i
这有一个较小的争用条件,但由于您的代码没有同步到任何东西,我认为这可能无关紧要。您只需锁定它,这意味着希望进入关键部分的其他线程将等待锁定,如果当前线程/任务释放它,它们将进入锁定 例如:TaskA获得锁,它现在处于临界区,并执行方法a()3次。当TaskA完成执行后,它会释放锁,可能还有上下文切换,因此TaskB会运行方法a()(第四次)。 TaskB返回后,主线程显示。。“嘿,TaskA已经完成,所以我验证我的结果”
除此之外,我不知道TaskA是否必须在TaskB之前运行。因此,我不知道任务调度程序是否为FIFO。这两种实现都已中断。请您解释一下,您的任务调度程序已中断,因为它不包含同步。他的被破坏了,因为它一直持有锁,任何调用函数的线程都会延迟。而且这个家伙是个白痴。如果您想同步一段特定的代码,而不是一个在许多地方使用的对象,那么可以使用bool not lock。而且他是个双重白痴,因为你不使用东西,因为它们看起来更多线程。。你使用它们是有原因的。如果他不能解释,别听他的好吧,也许是我的测试功能错误。。。在计时器调用期间,不完全模拟UI调用…我将使用david schwartz解决方案。有了他的解决方案,你将(大部分时间)得到你想要的结果为什么要使处理变得不稳定?volatile允许另一个线程访问该字段。否?使用volatile定义,线程必须始终读取主内存中的值,而不是线程自己的缓存中的值。感谢David和Lee的启示@Florian:除非您满足某些要求,否则不能保证一个线程会观察到另一个线程对变量的更改。满足这些要求的一种方法是将变量
设置为volatile
。例如,编译器可以通过删除\u isProcessing=true来自由优化代码代码>因为它只是被设置回false,并且没有代码可能分辨出差异(除非它违反了规则)。(注意,使用<代码> Value完全被C++破解):戴维:如果GUI调用在与定时器同时发生,那么两个线程都有可能看到“Y”处理为false。这是通过联锁防止的。
private object _locker = new Object();
public void JustDoIt(Action a, int interval, int times)
{
lock (_locker)
{
//_isProcessing = true;
for (int i = 0; i < times; i++)
{
a();
Thread.Sleep(interval);
}
}
//_isProcessing = false;
}
public void JustDoIt(Action a, int interval, int times)
{
if (_isProcessing) return
_isProcessing = true;
for (int i = 0; i < times; i++)
{
a();
Thread.Sleep(interval);
}
_isProcessing = false;
}