Запуск событий C # WPF асинхронно - PullRequest
1 голос
/ 10 марта 2019

Я пытался понять, как обрабатываются события приложения WPF.На этот вопрос, возможно, уже давали ответы, но все мои поиски приводили к ответам, слишком сложным для меня, чтобы я мог их понять, или просто немного не по теме.Однако я понимаю, что эти события выполняются синхронно.

В чем причина этого?И почему они не просто сделаны асинхронными?Можно ли заставить приложение запускать их все только некоторые из них асинхронно?

Спасибо!

Ответы [ 2 ]

0 голосов
/ 13 марта 2019

Когда вы говорите «События« Приложения »», вы имеете в виду только те, которые ОПРЕДЕЛЕНЫ на System.Windows.Application?ИЛИ ВЫ ТОЛЬКО имеете в виду любой объявленный event член в ЛЮБОМ классе?

Событие представляет собой набор делегатов метода: когда класс вызывает какое-то событие, он просто начинает вызывать обработчики.Если бы это было асинхронно, то создатель этого события не знал бы, кто мог бы его обработать, и отменяемое событие, такое как Window.Closing, не могло бы быть реализовано - ни один обработчик не гарантированно работал бы синхронно, и производитель всегда мог получитьчерез неотменяемое событие;делая это бесполезным.

Потребители также не знали бы, КОГДА они ПОЛУЧИЛИ событие!Если событие свойства изменено, они могут быть вызваны спустя много времени после того, как это свойство затем изменилось много раз, и кто знает, где приложение будет в это время!

МНОГИЕ СОБЫТИЯ СОЗДАНЫ, ЧТОБЫ БЫТЬ обрабатываться синхронно: приложение только что достигло некоторого состояния, и если вы не можете обработать событие синхронно, то это бесполезно - именно поэтому событие БЫЛО инициировано для начала.

Если события были асинхронными по "по умолчанию «тогда они становятся легко доступной асинхронной« шиной сообщений », и я думаю, что если вы оглянетесь назад, то обнаружите, что это тип« пустой траты времени ».Если все, что вы могли бы сделать в качестве продюсера событий, это запустить какое-то асинхронное неизвестное уведомление, то зачем вам беспокоиться ?!В этот момент производитель может также «скулить», чтобы реализовать какое-то асинхронное сообщение для КАЖДОГО действия - т.е. как бы вы пришли к определению того, что должно вызывать событие?(Где бы вы остановились, не дожидаясь каждого действия; которое вы МОЖЕТЕ реализовать с помощью инструментария.)

Существует множество библиотек с реализациями Application Message Bus.Благодаря уникальной асинхронной шине сообщений, охватывающей все приложения, вы можете иметь представление о службе, которой вы можете «предоставить» уведомление о событии.Если вы более четко определили эту вещь как место, где производители публикуют сообщения, а потребители могут подписаться на них, то у вас есть еще какое-то понятие об услуге, которую вы можете внедрить и использовать.Вы можете создать его для своего приложения, подписаться на существующие события и опубликовать их там, чтобы асинхронные потребители могли обрабатывать их ...

Вместо асинхронного по умолчанию теперь вы МОЖЕТЕ сами выбрать определение асинхронных событий, если выможет спроектировать это конкретное событие, чтобы быть полезным в асинхронной реализации.--- Повторение: вы НЕ будете достоверно знать, по умолчанию, ВОЗ обрабатывает событие, в какое время, если когда-либо.

Вы также можете переопределить любое существующее событие с новой версией Async и добавить синхронный обработчик, которыйповторно публикует каждое событие в асинхронной службе ... Но все сводится к дизайну, который требует некоторого асинхронного события;и асинхронное событие «по умолчанию» стало бы забытым, а кошмар с ошибками - для продюсера, который никогда не узнает, что происходит с событиями, которые он вызывает (и не может отладить их инвариантным способом).

... В библиотеках "Mvvm" есть шины событий;как MVVM Light.

0 голосов
/ 10 марта 2019

Когда событие вызывается, его обработчики вызываются последовательно.Причина, по которой они не являются асинхронными по умолчанию, заключается в том, что это создаст ненужные издержки и будет трудным для реализации.Такое поведение работает для всех событий в .NET и не имеет ничего общего с WPF.

Только один поток может получить доступ к пользовательскому интерфейсу в WPF.Все события пользовательского интерфейса в WPF возникают из этого потока пользовательского интерфейса.Если выполнение обработчика занимает много времени, поток пользовательского интерфейса будет заблокирован, пока обработчик не завершит выполнение, в результате чего приложение будет в состоянии «зависания».Причина этого не в этом вопросе и заслуживает отдельного объяснения.

Неверно считать события синхронными или нет.Это обработчики, которые являются синхронными или асинхронными.Поэтому невозможно просто указать в своем приложении, что все события по умолчанию являются асинхронными.Но можно сделать все (или некоторые) обработчики событий асинхронными.

Очень просто сделать обработчик событий асинхронным - просто пометьте его как async и await как длительное действие.Вы можете прочитать больше о async и await здесь .

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

...