我有一些必须连续运行的C#单元测试,因为它们清理整个数据库并设置指定的状态。并行执行此操作会导致不可预测的行为。出于这个原因,我试图在XML中将并行测试的数量设置为1,但它仍然进行了并行测试。所以我的下一个方法是使用[TestInitialize()]
和[TestCleanup()]
方法/扩展来强制进行串行处理。
这是我的代码:
static Object exclusiveDbAccess = new Object();
//Use TestInitialize to run code before running each test
[TestInitialize()]
public void MyTestInitialize()
{
lock (exclusiveDbAccess)
{
Monitor.Enter(exclusiveDbAccess);
}
}
//
//Use TestCleanup to run code after each test has run
[TestCleanup()]
public void MyTestCleanup()
{
lock (exclusiveDbAccess)
{
Monitor.Exit(exclusiveDbAccess);
}
}
这似乎在大部分时间都有效,但我有(甚至这很少)效果,看起来仍然有一些并行测试运行。 因为这总是发生在计算机上有很多负载时,我想知道这是不是由于“锁定()”之后的时间(例如10或30秒之后)。例如,如果在尝试获取锁定x秒失败后将跳过lock()块,则可能会导致这些问题。
所以我想请一位专家告诉我“锁定”声明的确切行为。请不要发布任何“猜测”。如果知道lock()超时体验报告当然是受欢迎的......
答案 0 :(得分:2)
这对我来说似乎是错误的用法。
lock(syncObject) { somecode }
基本上与
相同Monitor.Enter(syncObject);
try { somecode }
finally { Monitor.Exit(syncObject); }
所以在同一个对象上执行lock
和Monitor.Enter
/ Monitor.Exit
似乎不对
除非您明确设置了一些超时(如Monitor.TryEnter(syncObject, timeout)
)
请参阅msdn +
答案 1 :(得分:1)
他们没有超时 - 但您不应该使用lock
和 Monitor.Enter()
。
你应该这样做:
static Object exclusiveDbAccess = new Object();
//Use TestInitialize to run code before running each test
[TestInitialize()]
public void MyTestInitialize()
{
Monitor.Enter(exclusiveDbAccess);
}
//
//Use TestCleanup to run code after each test has run
[TestCleanup()]
public void MyTestCleanup()
{
Monitor.Exit(exclusiveDbAccess);
}
表单的lock
声明
lock (x) ...
的实现完全如下:
System.Threading.Monitor.Enter(x);
try {
...
}
finally {
System.Threading.Monitor.Exit(x);
}
(来自C#语言规范,第8.12节)