Это зависит от того, какое приложение вы пишете, например, принимаете ли вы ошибки?Каковы ваши требования к данным - софт в реальном времени?кислота?в конечном итоге согласованные и / или частично подключенные / иногда отключенные клиенты?
Остерегайтесь различий между параллелизмом и асинхронностью.Вы можете иметь асинхронность и, следовательно, вызывать чередование вызовов методов, фактически не имея одновременно выполняемой программы.
Одна из идей может заключаться в том, чтобы иметь сторону чтения и записи вашего приложения, где сторона записи публикует события, когда оно было изменено.,Это может привести к созданию системы, управляемой событиями - сторона чтения будет построена на основе опубликованных событий и может быть перестроена.Пользовательский интерфейс может быть управляемым задачей - в этом случае выполнение задачи приведет к созданию команды, которую будет выполнять ваш BL (или уровень домена, если вы того пожелаете).
Логический следующий шаг, если у вас есть вышеуказанное,это также пойти на основе событий.Затем вы воссоздали бы внутреннее состояние модели записи через то, что было зафиксировано ранее.Существует группа Google по CQRS / DDD, которая может помочь вам в этом.
Что касается обновления пользовательского интерфейса, я обнаружил, что интерфейсы IObservable в System.Reactive, System.Interactive, System.CoreEx хорошо работают.подходит.Он позволяет вам пропускать различные контексты одновременного вызова - диспетчер - пул потоков и т. Д., И он хорошо взаимодействует с библиотекой параллельных задач.
Вы также должны учитывать, куда вы помещаете свою бизнес-логику - есливы работаете с доменом, я бы сказал, что вы можете поместить его в свое приложение, так как у вас будет процедура обновления для двоичных файлов, которые вы распространяете в любом случае, когда придет время обновления, но есть также возможность разместить его на сервере.Команды могут быть хорошим способом выполнения обновлений на стороне записи и удобной единицей работы при сбое кода, ориентированного на соединение (они небольшие и сериализуются, а пользовательский интерфейс может быть сконструирован вокруг них).
Комуприведем пример, взгляните на этот поток , с этим кодом, который добавляет приоритет IObservable.ObserveOnDispatcher (...) - вызов:
public static IObservable<T> ObserveOnDispatcher<T>(this IObservable<T> observable, DispatcherPriority priority)
{
if (observable == null)
throw new NullReferenceException();
return observable.ObserveOn(Dispatcher.CurrentDispatcher, priority);
}
public static IObservable<T> ObserveOn<T>(this IObservable<T> observable, Dispatcher dispatcher, DispatcherPriority priority)
{
if (observable == null)
throw new NullReferenceException();
if (dispatcher == null)
throw new ArgumentNullException("dispatcher");
return Observable.CreateWithDisposable<T>(o =>
{
return observable.Subscribe(
obj => dispatcher.Invoke((Action)(() => o.OnNext(obj)), priority),
ex => dispatcher.Invoke((Action)(() => o.OnError(ex)), priority),
() => dispatcher.Invoke((Action)(() => o.OnCompleted()), priority));
});
}
ПримерВыше можно использовать, как это запись в блоге обсуждает
public void LoadCustomers()
{
_customerService.GetCustomers()
.SubscribeOn(Scheduler.NewThread)
.ObserveOn(Scheduler.Dispatcher, DispatcherPriority.SystemIdle)
.Subscribe(Customers.Add);
}
... Так, например, с виртуальным магазином Starbucks, у вас будет доменная сущность, которая имеет что-то вроде 'Barista'class, который производит события' CustomerBoughtCappuccino ': {cost:' $ 3 ', отметка времени:' 2011-01-03 12: 00: 03.334556 GMT + 0100 ', ... и т. д.}.Ваша читающая сторона подпишется на эти события.Сторона чтения может быть некоторой моделью данных - для каждого из ваших экранов, которые представляют данные - представление будет иметь уникальный класс ViewModel - который будет синхронизирован с представлением в наблюдаемом словаре , например ,Хранилище будет (: IObservable), и ваши докладчики подпишутся на все это или только на его часть.Таким образом, ваш графический интерфейс может быть:
- Управляемый задачами -> Управляемый BL, с акцентом на пользовательские операции
- Асинхронный
- Разделение на чтение-запись
Учитывая, что ваш BL принимает только команды и не отображает «модель, достаточную для всех страниц» типа чтения, вы можете сделать в нем большинство вещей внутренними, внутренними защищенными и частными.Это означает, что вы можете использовать System.Contracts, чтобы доказать, что в нем нет ошибок (!).Это произвело бы события, которые прочитала бы ваша модель чтения.Вы можете взять основные принципы из Caliburn Micro об организации рабочих процессов выполняемых асинхронных задач (IAsyncResults).
Существуют некоторые Rx рекомендации по проектированию , которые вы можете прочитать.И cqrsinfo.com о поиске событий и cqrs.Если вы действительно заинтересованы в том, чтобы выйти за пределы сферы асинхронного программирования в сферу параллельного программирования, Microsoft выпустила бесплатную книгу о том, как программировать такой код.
Надеюсь, это поможет.