У меня есть проблема, как ждут метод асинхронных в методах жизненного цикла WPF (с рамками Caliburn-Micro) (например, OnActivate, OnInitialized, OnExit -., Который связан непосредственно с Application.Exit события)Почему приложение Application.Exit работает, даже если обработчик является асинхронным в жизненном цикле приложений WPF?
Этих статья точно описывает мою проблему: http://mark.mymonster.nl/2013/07/10/donrsquot-make-your-application-lifetime-events-async-void (теперь я думаю о том, чтобы использовать решение этой статьи, но, похоже, немного перехитрил для первого взгляда)
Мне нужно дождаться некоторых методов асинхронизации в моем ящике OnExit, поэтому у меня есть это как асинхронный. И это работает. Вид. Я не понимаю почему ??, но при вызове события Application.Exit он как-то ждет, пока метод не будет завершен, даже если обработчик будет асинхронным. Можете ли вы объяснить, как это возможно? И это безопасно? Или это просто совпадение? Async void следует использовать только для Топ- событий, это тот случай?
Я просмотрел код системы. И связывания выглядит следующим образом:
public event EventHandler Exit
{
add
{
XcpImports.CheckThread();
this.AddEventListener(DependencyProperty.RegisterCoreProperty(20053U, (Type) null), (Delegate) value);
}
remove
{
XcpImports.CheckThread();
this.RemoveEventListener(DependencyProperty.RegisterCoreProperty(20053U, (Type) null), (Delegate) value);
}
}
который действительно загадочное, и я не могу увидеть, что на самом деле происходит в .NET Framework, вызвав это событие.
Что так же странно, что вызов ждут Task.Delay (1) в обработчик вызывает ТУПИК, когда я не использую ConfigureAwait (ложь). Поэтому я бы сказал, что есть где-то .Wait() используется глубоко в .net-коде.
Примечание: когда я делаю OnActivate, OnInitialized обработчики async, как и ожидалось, страница не дожидается завершения обработчика.
Thx для ваших ответов!
Я создал также новое приложение WPF и не смог воспроизвести тупик. После некоторого расследования я узнал, что это было вызвано нашей библиотекой регистрации, которая поддерживала приложение «живым», и именно поэтому OnExit был закончен. Фактически ** тупик действительно происходит **, но без этого компонента протоколирования вы его не видите, так как он * убит * сразу после закрытия приложения. Ваш шаблон для закрытия приложения звучит превосходно, я сделаю это! Но почему бы вам не рекомендовать решение из этой статьи? Мне все еще нужно, как ждать чего-то, например, в методе OnActivate. Такой помощник облегчит мою жизнь :) –
Код в этой статье (и ответы на него) не совсем корректен; IIRC не обрабатывает исключения правильно. Есть тонна * нюансов в том, что вы делаете это правильно, и даже если у вас есть отличная реализация, она все еще не может * работать в любой ситуации. [Стивен Туб имеет лучшее резюме этих хаков] (http://blogs.msdn.com/b/pfxteam/archive/2012/04/13/10293638.aspx); обратите внимание, что каждый описанный хак имеет серьезный недостаток. Не существует «одного решения», которое работает повсеместно. –
Лучшим решением является поиск альтернатив, например, 'await' в' OnActivate', скорее всего, асинхронная инициализация некоторого состояния, используемого для отображения (т. Е. ViewModel); правильным решением в этом случае является использование чего-то типа [асинхронного шаблона инициализации] (http://blog.stephencleary.com/2013/01/async-oop-2-constructors.html), который я описываю в своем блоге. Обратите внимание, что это правильное решение * * больше работы: вам нужно преднамеренно спроектировать состояние пользовательского интерфейса для «загрузки», а затем переход, когда завершение инициализации async завершено. –