如何确保在执行 async/await 时线程发生变化?

How to ensure a thread change when doing async/await?

在执行 await 时,Task 可能会也可能不会在同一个线程上执行。通常,我们只需要将这一事实纳入设计考虑即可。但我想专门针对线程更改场景进行测试 - 如何确保异步方法的其余部分(等待之后)在不同的线程上 运行?

可能的解决方案:

    [Test]
    public void TestForThreadChange()
    {
        int threadIdBefore, threadIdAfter = 0;

        async Task AsyncFunction()
        {
            Console.WriteLine($"before - {threadIdBefore = Thread.CurrentThread.ManagedThreadId}");
            await Task.Yield();
            Console.WriteLine($"after - {threadIdAfter = Thread.CurrentThread.ManagedThreadId}");
        }

        AsyncFunction().Wait();

        Assert.That(threadIdBefore, Is.Not.EqualTo(threadIdAfter));
    }

你不能。异步模式旨在以牺牲某些控制为代价来简化异步(duh)代码。如果需要控制线程创建,使用Thread/ThreadPool.

how do I ensure the rest of the async method (after await) is run on a different thread?

首先,确保您已从 thread-pool 上下文中调用被测试的方法。一些单元测试框架确实提供了 single-threaded 上下文。如果是这种情况,您需要将测试代码包装在 await Task.Run(() => ...).

然后,模拟正在等待的方法并确保它执行await Task.Yield();这将确保被测方法中的 await 将获得未完成的任务,导致它在线程池线程上恢复。

如果您想绝对确定它会在不同的线程池线程上恢复,您需要阻塞您的单元在被测方法上测试方法,使当前线程池线程阻塞,不用于恢复被测方法。