这里的场景:
计时器每分钟调用一个方法。可以通过 UI(按钮)调用此方法。我希望如果我的方法“正在进行中”并且被调用,它不会执行该方法两次。
在我的方法中,我使用了一个简单的布尔值:
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;
}
它工作正常。我用这个测试测试这个功能:
[Test]
public void Should_Output_A_String_Only_3_Times()
{
var consoleMock = new Mock<IConsole>();
IConsole console = consoleMock.Object;
var doer = new Doer { Console = console };
Action a = new Action(() => console.Writeline("TASK DONE !"));
// Simulate a call by Timer
var taskA = Task.Factory.StartNew(() => doer.JustDoIt(a, 1000, 3));
// Simulate a call by UI
var taskB = Task.Factory.StartNew(() => doer.JustDoIt(a));
taskA.Wait();
consoleMock.Verify(c => c.Writeline("TASK DONE !"), Times.Exactly(3));
}
一位开发人员查看了我的代码并说:“我用lock
关键字替换了您的布尔值。它更线程安全。坦率地说,我没有掌握多线程,所以我回答他“OK Guy!”
几天后(今天更准确地说),我想测试使用锁或简单布尔值之间的区别。因此,当我用 lock 关键字替换布尔值时,我很惊讶,如下所示:
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;
}
先例测试不通过:
消息:Moq.MockException:对模拟的预期调用正好 3 次,但实际是 4 次:c=>c.Writeline("TASK DONE !")
那么,我是否错误地使用了 lock 关键字?它应该是“静态的”吗?
谢谢