requirement: Refresh data periodically using timers on the Silverlight user interface.
When using asynchronous request data in a DispatcherTimer Tick event in Silverlight, there are multiple requests , and the following is the code for ViewModel, which looks fine:
usingSystem;usingSystem.Net;usingSystem.Threading;usingSystem.Windows;usingSystem.Windows.Controls;usingSystem.Windows.Documents;usingSystem.Windows.Ink;usingSystem.Windows.Input;usingSystem.Windows.Media;usingSystem.Windows.Media.Animation;usingSystem.Windows.Shapes;usingSystem.Windows.Threading;namespaceasynctest.viewmodel{ Public classMainpageviewmodel:notificationbase {Private intcount; Public intCount {Get { returncount; } Set { This. Count =value; Base. OnPropertyChanged ("Count"); } } protectedWcfservice.service1client client =NULL; PrivateDispatcherTimer timer =NULL; protected intInterval =1; PublicMainpageviewmodel () {Client=Newwcfservice.service1client (); Timer=NewDispatcherTimer (); Timer. Interval=NewSystem.TimeSpan (0,0, Interval); Timer. Tick+=Timer_tick; Timer. Start (); } Private voidTimer_tick (Objectsender, EventArgs ee) {Client. Getdataasync (); Client. Getdatacompleted+ = ((s, e) = = { This. count++; }); } }}
However, the result is not what we expected, and after each request succeeds, count will accumulate in such a sequence: 1 3 6 10 15 21.
After debugging for three days, excluding the view layer on the ViewMode has been initialized many times to create the instance of the timer, the possibility of many other cases are excluded, and finally locked the problem in the method body tick.
Later after repeated debugging, finally know the problem where the special, I 艹, allow me to explode a foul language, engaged for two or three days, mom eggs, only to find the problem so simple , carefully observe the code, you can see this is an event-based asynchronous programming model .
Problem: In the Tick method, the client. getdatacompleted+= ((s,e) =>{//do something}); , then every time the tick execution cycle will be "+ =" an event, so give us the illusion of multiple requests , is actually requested once, just a number of times executed completed event.
This is why the result of count is not what we expected 1 2 3 4 5 6 ..., the code that was modified is as follows:
private void Timer_tick (object sender, EventArgs ee) {client. Getdataasync (); Client. getdatacompleted += client_getdatacompleted; void client_getdatacompleted (object< /span> sender, Wcfservice.getdatacompletedeventargs e) { // Remove the event to prevent the next tick event from registering the client again. getdatacompleted-= client_getdatacompleted; this . Count++
Completed events are presented separately, after each entry to the completed, use "-=" to unregister the event, again into the tick, re-request, re-bind is OK, It is also possible to bind the completed event directly in the ViewModel constructor, requesting only Client.getdataasync () in each tick, and no +=client_getdatacompleted is required, both methods are available.
Note: The actual project used is the Client_getdatacompeleted event E.result, here is to facilitate debugging write a demo, the purpose of using count is to monitor the implementation of compeleted in the end several times.
experience: each encounter problems, not impatient, can be complicated to simple, if you do not know where the problem can be used to eliminate the problem one by one, and finally find the problem, careful analysis, continuous debugging, to find the problem at the root, to be resolved.
Finish!
Using an event-based asynchronous request in the DispatcherTimer tick in Silverlight