Если вы уничтожите поток, который запустил задачу `async`, вы убьете задачу? - PullRequest
1 голос
/ 22 января 2020

Одна из ловушек метода async заключается в том, что операция может выполняться в разных потоках. Это можно проверить с помощью:

var z = 0;
while (z < 20)
{
   Console.Write(" - Thread: " + Thread.CurrentThread.ManagedThreadId);
   await Task.Delay(1000);
   z++;
}

, который выведет что-то вроде:
- Thread: 1 - Thread: 1 - Thread: 4 - Thread: 6 - Thread: 7 - Thread: 4

При обычном подходе, если вы используете:

var z = 0;
while (z < 20)
{
   Console.Write(" - Thread: " + Thread.CurrentThread.ManagedThreadId);
   Thread.Sleep(1000);
   z++;
}

ваш вывод будет:
- Thread: 1 - Thread: 1 - Thread: 1 - Thread: 1 - Thread: 1 - Thread: 1

Теперь, если вы инкапсулируете первый код в Thread следующим образом:

var thread = new Thread(new ThreadStart(async () =>
{
    var z = 0;
    while (z < 20)
    {
        Console.WriteLine("Thread: " + Thread.CurrentThread.ManagedThreadId);
        await Task.Delay(1000);
        z++;
    }
}));
thread.Start();

если вы thread.Abort надежно убить async запущенную операцию?

Ответы [ 3 ]

3 голосов
/ 23 января 2020

Идея асинхронного c метода заключается в том, что операция может выполняться в разных потоках.

Нет. Идея метода async - это метод, который можно приостановить во время выполнения другой операции, а затем возобновить позже. Некоторые async методы могут возобновиться в разных потоках; другие не могут.

, если вы работаете с потоком. Аборт будет ли вы надежно уничтожать запущенную операцию asyn c?

Нет. Как только метод достигнет первого await, поток завершится. Если Thread.Abort выполняется до того, как поток достигнет await, код будет прерван. Если Thread.Abort выполняется после того, как поток выполняет await, поток уже будет выходить.

2 голосов
/ 22 января 2020

Идея асинхронного c метода заключается в том, что операция может выполняться в разных потоках.

Идея асинхронного c метода заключается в том, что операция должна выполняется асинхронно и не обязательно в отдельном потоке. Некоторые операции ввода / вывода не требуют потоков пула потоков и вместо этого выполняются в потоках ввода / вывода.

Вот несколько соображений, которые я хотел бы рассмотреть:

  • Ключевое слово await создает конечный автомат, который обрабатывает асинхронную операцию c и ее продолжение.

  • Смешивание потоков с кодом async пахнет и не рекомендуется.

  • Технически, если операция asyn c выполняется в потоке пула потоков, прерывание потока, в котором она запущена, не завершит операцию, однако, скорее всего, это означает, что вы не Не важно, как заканчивается операция async, и вы не сможете ее обработать, если она находится в неисправном состоянии.

  • Метод Thread.Abort не поддерживается в .Net Core и если вы запустите его, вы увидите:

    "Необработанное исключение. System.PlatformNotSupportedException: прерывание потока не поддерживается на этой платформе"

1 голос
/ 22 января 2020

Вы пробовали пройти этот код с помощью отладчика? Я думаю, что вы обнаружите, что, поскольку ничего не ждет async внутри ThreadStart, поток будет выполнен немедленно, как только он встретит первый await, и l oop будет прекращено.

Почему? Поскольку async/await не был предназначен для выполнения метода в нескольких потоках . Тот факт, что он может это сделать, является побочным продуктом его предназначения.

Он был разработан, чтобы позволить, в какой-то момент, дальше по стеку вызовов, потоку делать другие вещи (например, слушать пользовательский интерфейс). входы), в то время как асинхронная часть работы продолжается. Поведение await - вернуть управление родительскому вызывающему. Поскольку родительский вызывающий абонент отсутствует, поток завершается при await.

. Вас может заинтересовать мой ответ здесь , где это объясняется более подробно.

...