При выполнении awaitTask может или не может выполняться в том же потоке. Обычно нам просто нужно учитывать этот факт при проектировании. Но я хотел бы сделать тест специально для сценария смены потока — как мне убедиться, что остальная часть асинхронного метода (после ожидания) выполняется в другом потоке?
Возможное решение:
[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));
}
@PeterDuniho, да, именно это я и имел в виду ... вам просто нужно знать, что изменение потока может произойти, и разработать код, который не зависит от того, работает ли он в том же или другом потоке.





Вы не можете. Асинхронный шаблон предназначен для упрощения асинхронного кода за счет некоторого контроля. Если вам нужно управлять созданием потока, используйте Thread/ThreadPool.
how do I ensure the rest of the async method (after await) is run on a different thread?
Во-первых, убедитесь, что вы вызвали тестируемый метод из контекста пула потоков. Некоторые среды модульного тестирования предоставляют однопоточный контекст. Если это так, вам нужно обернуть код тестирования в await Task.Run(() => ...).
Затем смоделируйте ожидаемый метод и убедитесь, что он выполняет await Task.Yield(); это гарантирует, что await в тестируемом методе получит незавершенную задачу, что приведет к ее возобновлению в потоке пула потоков.
Если вы хотите, чтобы абсолютно уверен возобновлялся в потоке пула потоков разные, вам необходимо заблокировать метод модульного тестирования в тестируемом методе, чтобы текущий поток пула потоков был заблокирован и не использовался для возобновления тестируемого метода. .
Спасибо, @stephen-cleary. Именно туда я и направлялся. Я просто не был уверен в блокирующей части. Разве теоретически не возможно, что даже если асинхронный метод возвращает незавершенную задачу, он все равно должен быть выполнен до того, как тестовый метод достигнет Wait()? Я добавил возможное решение к ответу.
@mivra: Да, он может завершиться до того, как его ожидают. Ваше решение не гарантирует возобновления работы метода в другом потоке; Я бы рекомендовал заблокировать задачу вместо использования await, чтобы гарантировать, что она возобновится в другом потоке.
о, тогда просто используйте Wait() для асинхронной функции. Я правильно понял?
да. Таким образом, поток, который запускает асинхронный метод, блокируется и не может быть использован для его возобновления.
Я не уверен в значении. Я думаю, у вас был асинхронный метод или коллекция, тогда вы могли бы использовать Task.Wait, Task.WaitAll, Task.Any. Я не уверен, что вы можете получить информацию об этом низкоуровневом потоке, не изобретая заново некоторые колеса. Вы можете сохранить поток в какой-то потокобезопасный список с собственным идентификатором, и вы можете отслеживать это.