I am currently getting started with the .NET Prism framework to develop a WPF application. One thing that I'm unable to determine is the best way to achieve asynchronous calls to a WCF service, or a database? The reason is, I don't want a WCF/DB call to block the UI thread, which causes the UI to just freeze until the operation is done.
From my understanding, I should be following the architecture:
View (WPF) <=> View Model <=> Application Services <=> DB/WCF
Do I implement the asynchronous behaviour in the view model using something like the AsyncDelegateCommand? If I do this, then I am unable to maintain any state in the application services, since setting any state needs to be done in the UI thread (unless there's a way around this).
So the other option is to provide async methods with callbacks in the application services and have the application services spawn threads/tasks for the asynchronous operations.
I briefly looked into the Prism StockTrader reference implementation, and they don't seem to do anything asynchronously. I feel that this should be a very common problem,开发者_开发技巧 and there must be some best practices out there to deal with this.
I haven't found anything online in terms of a "Best Practice".
Personally I think the following setup is good: View <= BINDING => ViewModel <==> DataRepository/DataAccessLayer (Async Calls)
As far as keeping your ViewModel in sync with the DAL you can do a couple of things depending on what data is needed to be synced:
- Expose
ReadOnlyObservableCollection<T>
s for collections of your models and manage their backing collections internally (from within the DAL). - For single items return a new instance of the item and load the item on the async completed event.
- Also, learn to love the EventAggregator (it's not overly complex -- Though, there are improvements to it online -- EventAggregator Extension). It helps a lot. It's better to use this to announce "working" and "completed" events.
Basically, since the Service Reference Generator helps build Async calls for you, just work with that and use your DataRepository/DAL to manage the data internally exposing references to your ViewModels and the EventAggregator to announce Working/Completed.
I should also say this... you can choose to make your DAL completely synchronous and have all async calls to/from it on the ViewModel since you'll probably want to expose some type of "IsWorking/Completed" properties to let the view know something is happening or it's done. I think the key is to ensure that you stick all asynchronousity on one layer (not the View though). Doing it on the ViewModel layer makes it more coding work building the async calls, but it's a lot cleaner. You're DAL only does things synchronously and does not have to publish completed/isworking events. In fact, I'd actually say this is the more common approach.
精彩评论