Wait () вызывает зависание потока пользовательского интерфейса - когда следует использовать Wait ()?
У меня есть следующий код, который подключается к узлу SignalR
private static async Task StartListening()
{
try
{
var hubConnection = new HubConnection("http://localhost:8080/");
IHubProxy hubProxy = hubConnection.CreateHubProxy("Broadcaster");
hubProxy.On<EventData>("notifyCardAccessEvent", eventData =>
{
Log.Info(string.Format("Incoming data: {0} {1}", eventData.Id, eventData.DateTime));
});
ServicePointManager.DefaultConnectionLimit = 10;
await hubConnection.Start();
Log.Info("Connected");
}
catch (Exception ex)
{
Log.Error(ex);
}
}
В моем методе Form_Load у меня есть этот
StartListening();
Однако Resharper предлагает мне "рассмотреть возможность применения оператора 'await' к результату вызова "
Так я и сделал:
Log.Info("Connecting to SignalR hub...");
StartListening().Wait();
Log.Info("Connected!");
Однако это приводит к зависанию потока пользовательского интерфейса и Connected! никогда не печатается в файл журнала.
Wait()? Каковы примеры и сценарии, которые я должен использовать Wait (), и когда следует Я не использую Wait()?3 ответа:
awaitне являетсяWait. Неясно, что это за код, который вызываетStartListening(), но один из вариантов-этоawait, как было предложено:await StartListening();Однако, в некоторых других случаях это может быть лучше вообще ничего не делать:
StartListening(); // drop the Task on the floorИли, возможно, использовать
ContinueWithдля ручного продолжения. Поскольку методStartListeningловит любые исключения, нет ничего плохого в том, чтобы просто игнорировать возвращенныйTask- так что у вас уже было. Хотя я бы предложил назвать егоStartListeningAsync.Причина возникновения взаимоблокировка заключается в том, что если вы используете
Wait, ваш поток пользовательского интерфейса блокирует ожидание завершения асинхронного метода, но этот асинхронный метод захватывает контекст синхронизации, что означает, что для обработки каждого продолжения он пытается попасть в поток пользовательского интерфейса, который блокируется... на нем .
@MarcGravell имеет правильный ответ; я просто отвечу на этот другой вопрос:
Путаница возникает из-за того, что типИтак, мой вопрос заключается в том, когда я должен использовать Wait()? Каковы примеры и сценарии, которые я должен использовать Wait (), и когда я не должен использовать Wait()?
Taskиспользуется для двух почти совершенно разных вещей.
Taskпервоначально был представлен в .NET 4.0 как часть параллельной библиотеки задач. Обычно, ты будет использовать параллельный LINQ или классParallelдля параллельной обработки (который использовал типTaskвнизу). Однако в расширенных сценариях можно использовать типTaskнепосредственно.Task.Waitиспользовался для ожидания завершения этих независимых задач.Когда
async/awaitбыли введены в .NET 4.5, существующий типTaskбыл почти достаточно хорош, чтобы использоваться в качестве абстрактного "будущего". Поэтому вместо того, чтобы изобретать какой-то новый тип" будущего", они просто немного расширилиTask, чтобы работать как будущее.Это приводит нас к сегодняшнему дню, где
Taskможет использоваться как:
- элемент работы в параллельном вычислении.
- асинхронное будущее.
(есть крошечный кроссворд: вы можете рассматривать параллельную работу как асинхронную, и в редких ситуациях, таких как консольные методы
Main, Вам нужно блокировать асинхронные задачи; но на данный момент игнорируйте их.)Это означает, что API для
Taskразбивается по этим линиям. Члены такие какStart,Wait,Result, иContinueWithдовольно прочно принадлежат параллельной стороне. В асинхронном миреawaitболее уместно.У меня есть маленький столик в нижней части моего
asyncвведение , которое имеет некоторые новые (асинхронные) эквиваленты для старых (параллельных) способов выполнения вещей.
Вы, кажется, неправильно поняли сообщение от Решарпера. Вместо применения оператора
awaitвы вызвали методTask.Wait(). Они могут казаться похожими, но работают совершенно по-разному.Этот приятный ответ даст больше информации о различиях: https://stackoverflow.com/a/13140963/3465395