событие или действие при завершении метода?

#wpf #events #asynchronous #delegates #prism

#wpf #Мероприятия #асинхронный #делегаты #призма

Вопрос:

Предполагая, что у вас есть папка электронной почты и сообщения в ней. Каждое сообщение имеет свойство Body, которое должно загружаться асинхронно и уведомлять вас о завершении, как бы вы подошли к этому?

1 — Сообщение.LoadBody() сообщение о событии.BodyLoadComplete

2 — Сообщение.LoadBody(действие завершено)

Для полноты картины задействованы WPF и Prism.

Спасибо!

Редактировать:

Сообщение будет объектом пользовательского интерфейса, который обернет интерфейс iMessage (который не готов к пользовательскому интерфейсу (нет INPC)), поэтому причина, по которой я спрашиваю, заключается в том, что мы должны согласиться на интерфейс между пользовательским интерфейсом и бизнес-уровнем.. iMessage. (Бизнес-уровень будет использовать библиотеку Imap, которая уже имеет некоторый асинхронный шаблон, но мы не хотим слишком сильно зависеть от какого-либо imp, поэтому я пытаюсь найти лучший интерфейс..

Комментарии:

1. Более описательным и открытым заголовком может быть «Лучший шаблон для асинхронных методов?»

2. я не обсуждаю шаблоны aync, плюс в таком потоке это всегда заканчивается «зависит от того, что вы делаете»

Ответ №1:

Если вы используете .NET 4, я бы использовал:

 Task<string> LoadBodyAsync()
  

(Возможно, вы захотите реализовать это с помощью TaskCompletionSource<TResult> .)

Затем вызывающий может добавлять продолжения и т. Д., Как они пожелают … и самое главное, в дивном новом мире .NET 4.5 и C # 5 это будет работать без проблем с async / await features .

Комментарии:

1. Внутри тела загрузки вызывается другая библиотека imap, которая выполняет загрузку в другой поток, поэтому использование Task тоже было моей первой идеей, но в данном случае это не совсем вариант..

2. @Zapacila: Почему нет? Высказывание «это не вариант» точно не дает много информации.

3. @Joe было бы 2 потока, один из которых был создан задачей, а 1 — библиотекой inap..

4. @Zapacila: Не обязательно. Я не предлагал использовать Task.Factory.StartNew — я предложил использовать TaskCompletionSource<TResult> . Вы можете установить результат для источника завершения задачи после завершения операции IMAP.

5. @Joe Awesoomeрешение, я виноват в том, что забегаю вперед. Я прочитал больше о TaskCompletionSource на blogs.msdn.com/b/pfxteam/archive/2009/06/02/9685804.aspx и это совпадение. Теперь интерфейс iMessage может иметь другие события при изменении данных, должны ли мы смешивать эти 2 разные парадигмы?

Ответ №2:

Из ваших двух вариантов:

 Message.LoadBody() // Plus an event, Message.BodyLoadComplete

// or ...

Message.LoadBody(Action completeDelegate)
  

Опция события является более гибкой и иногда может быть менее болезненной в использовании. Если вам все равно, когда или если LoadBody завершается, то вы не обязаны предоставлять поддельный обратный вызов. И вы можете привязать событие завершения к нескольким обработчикам событий, что иногда может быть полезно (например, если необходимо обновить несколько элементов управления пользовательского интерфейса).

Однако оба ваших решения нетипичны. Типичный «старый» способ сделать это — LoadBody разделить на BeginLoadBody и EndLoadBody и предоставить пользователю IAsyncResult . См. Эту статью. Типичный «новый» способ сделать это изложен в ответе Джона Скита.

Ответ №3:

Если вы используете Prism, вам следует рассмотреть возможность использования EventAggregator и публикации сообщения, чтобы указать, что почта загружена. Это позволит вам легко иметь несколько слабо связанных подписчиков для этого «события».

Использование EventAggregator является элегантным решением для публикации событий и приводит к гораздо более чистой и развязанной архитектуре, которую легче расширять. Например, если вы хотите добавить новую функцию к загрузке электронной почты, такую как индикация хода выполнения, вы можете просто подписаться на EmailLoaded сообщение, и все готово, вам не нужно жестко связывать ваш новый компонент с электронными письмами через событие или обратный вызов, им не нужно знать друг о друге.