Return 线程锁定到 ThreadPool

Return thread to ThreadPool on lock

当我像这样锁定 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;
}

如果调用此方法的并发线程多于线程池中的线程,所有这些线程最终都会等待锁定,而其他地方发生的异步代码无法继续,因为它正在等待中的空闲线程线程池。

所以我不想阻塞线程,我需要在等待时将它 return 到 ThreadPool。
有没有其他方法可以将 return 等待线程锁定到线程池?

使用 xUnit ~1.7+,你可以做的主要事情是让你的测试方法 return Task<T> 然后使用 async/await 这将限制你的hard-blocking/occupation 个线程

xUnit 2.0 + 具有并行执行和 mechanism for controlling access to state to be shared among tests。但是请注意,这基本上是通过 运行一次在测试 Class 中进行一项测试并一次将 Class 夹具 提供给一个测试来运行的(这相当于通常发生的情况 - 每 class 运行 一次只有一个测试方法)。 (如果您使用 Collection Fixture,实际上集合中的所有测试 Class 都会变成一个测试 Class)。

最后,xUnit 2 提供开关来控制是否:

  • 组件运行与其他[组件]
  • 并行
  • 测试 Collections/Test Classes 运行 与其他人并行
  • 前两个

您应该能够通过不隐藏 asyncness 来管理您的问题,而是将其暴露给测试方法或通过 [=16 构建 up/teardown =]

任何必须在锁内完成的工作都应移至任务中,该任务在测试之前启动,并在创建资源时完成。

每当测试想要获取任务创建的资源时,它可以在访问资源之前在 creator-task 上使用 await 进行阻塞。所以对资源的所有访问都在任务中,不能阻塞池的所有线程。

类似于:

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;
}