当我像这样锁定ThreadPool上的线程时,线程被阻塞:
private static object _testServerLock = new object();
private static TestServer _testServer = null;
public TestServer GetServer()
{
lock (_testServerLock)
{
if (_testServer == null)
{
_testServer = new TestServer(); // does some async stuff internally
}
}
return _testServer;
}
如果我有更多的并发线程调用它,那么我在ThreadPool中有线程,所有这些线程都会等待锁定,而其他地方发生的异步代码无法继续,因为它正在等待一个免费线程ThreadPool。
所以我不想阻止该线程,我需要在等待时将其返回给ThreadPool。
还有其他一些锁定方法可以将等待的线程返回给ThreadPool吗?
答案 0 :(得分:1)
在锁内部必须完成的任务都应该移动到一个任务中,该任务在测试完成之前启动,并在创建资源时启动。
每当测试想要获取任务创建的资源时,它都可以在访问资源之前使用await on creator-task进行阻止。因此,对资源的所有访问都在任务中,并且不能阻止池中的所有线程。
类似的东西:
private static object _testServerLock = new object();
private static TestServer _testServer = null;
private static Task _testTask = null;
private async Task<TestServer> CreateTestServerAsync()
{
...
}
// Constructor of the fixture
public TestFixture()
{
// The lock here may be ok, because it's before all the async stuff
// and it doesn't wait for something inside
lock (_testServerLock)
{
if (_testTask == null)
{
_testTask = Task.Run(async () => {
// it's better to expose the async nature of the call
_testServer = await CreateTestServerAsync();
});
// or just, whatever works
//_testTask = Task.Run(() => {
// _testServer = new TestServer();
//});
}
}
}
public async Task<TestServer> GetServerAsync()
{
await _testTask;
return _testServer;
}
更新
您可以使用静态成员的初始化来删除锁定。
private static TestServer _testServer = null;
private static Task _testTask = Task.Run(async () => {
_testServer = await CreateTestServerAsync();
});
private static async Task<TestServer> CreateTestServerAsync()
{
...
}
public TestFixture()
{
}
public async Task<TestServer> GetServerAsync()
{
await _testTask;
return _testServer;
}
答案 1 :(得分:0)
使用xUnit~1.7 +,你可以做的主要是让你的测试方法返回Task<T>
,然后使用async
/ await
这将限制你的硬阻塞/占用线程
xUnit 2.0 +具有并行执行和mechanism for controlling access to state to be shared among tests。但请注意,这基本上是通过一次在Test Class中运行一个测试并一次一个地给出 Class Fixture (这相当于通常发生的情况 - 每个类只运行一个测试方法)来实现的。在一个时间)。 (如果使用 Collection Fixture ,则集合中的所有测试类都会成为单个测试类。
最后,xUnit 2提供了用于控制是否的开关:
您应该能够通过不隐藏async
所做的事情来管理您的问题,而是将其暴露给测试方法或通过IAsyncLifetime
进行构建/拆除