Является Async/Await с помощью Task.Run запускает новый поток асинхронно?
Я прочитал много статей и все еще не могу понять эту часть.
Рассмотрим этот код:
private async void button1_Click(object sender, EventArgs e)
{
await Dosomething();
}
private async Task<string> Dosomething()
{
await Task.Run((() => "Do Work"));
return "I am done";
}
Первый вопрос:
Когда я нажимаю кнопку, он вызывается DoSomething и ждет Task, который создает Thread из потока thread, вызывая Task.Run(если я не ошибаюсь), и все это выполняется асинхронно. Итак, я добился создания потока, который выполняет мою работу, но делает это асинхронно? Но учтите, что мне не нужен какой-либо результат, я просто хочу, чтобы работа была выполнена без получения какого-либо результата, действительно ли нужно использовать async/await, и если да, то как?
Второй вопрос:
При запуске потока асинхронно, как это работает? Он работает на основном пользовательском интерфейсе, но на отдельном потоке или работает на отдельном потоке и раздельно асинхронно внутри этого метода? Я, возможно, испортил разницу между асинхронными методами и потоками, поэтому, пожалуйста, расскажите мне обо мне.
Ответы
Ответ 1
- Цель создания методов Async заключается в том, что вы можете ожидать их позже. Как будто "Я собираюсь положить эту воду на кипение, закончить приготовление остальной части моих ингредиентов супа, а затем вернуться в горшок и ждать, пока вода закончит кипение, чтобы я мог приготовить обед". Вы начинаете кипение воды, которое оно делает асинхронно, в то время как вы делаете другие вещи, но в конечном итоге вы должны остановиться и дождаться его. Если вы хотите "стрелять и забыть", тогда не нужны Async и Await.
Простейший способ сделать огонь и забыть метод в С#?
- Запуск новой задачи приостанавливает выполнение этой задачи в потоке threadpool. Темы выполняются в контексте процесса (например, исполняемый файл, который запускает ваше приложение). Если это веб-приложение, работающее под IIS, то этот поток создается в контексте рабочего процесса IIS. Этот поток выполняется отдельно от основного потока выполнения, поэтому он отключается и выполняет свою работу независимо от того, что делает ваш основной поток выполнения, и в то же время ваш основной поток выполнения перемещается с его собственной работой.
Ответ 2
Тип Task<TResult>
требует возврата TResult
из вашей задачи. Если вам нечего возвращать, вы можете вместо этого использовать Task
(что, кстати, является базовым классом Task<TResult>
).
Но имейте в виду, что задача не является нитью. Задача - это задание, в то время как поток является рабочим. По мере запуска вашей программы рабочие места и рабочие становятся доступными и недоступными. За кулисами библиотека назначит ваши рабочие места доступным рабочим, и, поскольку создание новых рабочих является дорогостоящей операцией, она обычно предпочитает повторно использовать существующие из пула потоков.
Ответ 3
1
Там большая разница, если вы не await
Task
или вы await
it:
-
Дело в том, что вы не await
it: DoSomething
вызывается, но следующее предложение выполняется, пока DoSomething
Task
не завершено.
-
Вы вызываете await
it: DoSomething
и следующее предложение выполняется после завершения DoSomething
Task
.
Таким образом, необходимость async
/await
будет зависеть от того, как вы хотите вызывать DoSomething
: если вы не await
, это похоже на вызов огня и забудьте способ.
2
Работает ли он на основном пользовательском интерфейсе, но на отдельном потоке или работает на отдельной нити и отдельно асинхронно внутри метод?
Асинхронный код иногда означает другой поток (см. этот Q & A Асинхронный и многопоточность - есть разница?). То есть, если код выполняется в отдельном потоке из пользовательского интерфейса, или он позволяет продолжить обработку потока пользовательского интерфейса во время его возобновления, это хорошо, потому что петля пользовательского интерфейса все еще может обновлять экран, в то время как другие задачи выполняются в параллельной без замораживания пользовательского интерфейса.
Асинхронный метод (т.е. метод async
) является синтаксическим сахаром, чтобы сообщить компилятору, что операторы await
следует рассматривать как конечный автомат. Компилятор С# превращает ваш код async
/await
в конечный автомат, где после ожидаемого кода выполняется код, ожидающий результата Task
.
Интересный Q & As
Возможно, вам захочется просмотреть эти другие Q & As:
OP сказал...
[...] Но означает ли это, что "async/await" сработает поток и Task.Run также запускает нить или они оба являются одним и тем же потоком?
Использование async
- await
не означает "Я создаю поток". Это просто синтаксический сахар, чтобы воплотить его в элегантном стиле. Задача может быть или не быть нитью. Например, Task.FromResult(true)
создает поддельную задачу, чтобы иметь возможность реализовать метод async без необходимости создания потока:
public Task<bool> SomeAsync()
{
// This way, this method either decides if its code is asynchronous or
// synchronous, but the caller can await it anyway!
return Task.FromResult(true);
}