Как убедиться, что Task не будет повторно использовать вызывающий поток в TPL? - PullRequest
0 голосов
/ 24 июня 2019

Я развиваюсь ASP.Net Web Api.Я использую async методы для запуска асинхронного кода при необходимости.Также у меня есть несколько конкретных случаев, когда мне нужно заблокировать эти async методы, чтобы получить результат.Поскольку блокировка асинхронных методов в потоке ASP.Net Request вызывает тупик (объяснение, почему можно найти здесь ), я решил заблокировать асинхронные методы в отдельной задаче, используя Task.Run.Рассмотрим следующий пример:

public class TestController : ApiController
{
    // This method must be synchronous
    public void Test()
    {
        Debug.WriteLine($"Main Thread {Thread.CurrentThread.ManagedThreadId}");
        // I must use a Task here because otherwise I will have to block async code which will cause a deadlock
        var task = Task.Run(() =>
        {
            Debug.WriteLine($"Child Thread {Thread.CurrentThread.ManagedThreadId}");
            SomeAsynchronousWork().GetAwaiter().GetResult();
        });
        task.GetAwaiter().GetResult();
    }

    public async Task SomeAsynchronousWork()
    {
       // some work that must be done asynchronously
    }
}

Теперь иногда, когда запускается метод Test, я вижу этот вид отладочного вывода

Main Thread 5
Child Thread 5

Это означает, что задача была запущена на том женить, которая вызвала тупик.Это очень странно для меня, потому что в моем понимании Task.Run должен запускать задачу в потоке ThreadPool, и он никогда не может быть основным потоком (поток запроса ASP.Net в этом примере).Видимо, это не так.У меня есть вопросы:

  1. Как это возможно?
  2. Как я могу убедиться, что Задача всегда будет выполняться в потоке ThreadPool, а не в вызывающем ASP.Net Requestthread?

Также обратите внимание, что из-за некоторых деталей, которые я не хочу здесь объяснять, я ДОЛЖЕН блокировать асинхронные методы, и нет способа сделать мои методы асинхронными вплоть до самого верха.

...