Silverlight入门系列应用MVVM模式10BackgroundWorkder和MVVM.docx
《Silverlight入门系列应用MVVM模式10BackgroundWorkder和MVVM.docx》由会员分享,可在线阅读,更多相关《Silverlight入门系列应用MVVM模式10BackgroundWorkder和MVVM.docx(12页珍藏版)》请在冰豆网上搜索。
Silverlight入门系列应用MVVM模式10BackgroundWorkder和MVVM
Silverlight下这个BackgroundWorker我们应当很熟悉了,以前在WinForms下面就有;当我们需要在当前UI线程之外的线程处理耗时的操作而不阻塞UI线程,就可以用这个BackgroundWorker.用起来也是很方便,需要注意的是在DoWork事件中不要操作UI线程的内容,把UI操作都放到ReportProgress事件处理和WorkCompleted事件处理中。
记住这两点就可以了。
今天讲的是Silverlight如何在MVVM模式下用BackgroundWorker。
总体原则就是把后台耗时业务处理和界面逻辑分开,既实现多线程,又实现界面和逻辑分离。
主要BackgroundWorker代码:
ViewModel代码:
(里面有个Command启动耗时任务,任务中ReportProgress事件处理和WorkCompleted事件通知UI)
1:
usingSystem;
2:
usingSystem.ComponentModel;
3:
usingSystem.Windows.Input;
4:
5:
namespaceBackgroundWorkerTest
6:
{
7:
publicclassViewModel:
INotifyPropertyChanged
8:
{
9:
publicICommandStartTaskCommand{get;privateset;}
10:
privateint_counter=0;
11:
12:
publicViewModel()
13:
{
14:
StartTaskCommand=newDelegateCommand(StartTask,CanStartTask);
15:
}
16:
17:
privatevoidStartTask(objectparam)
18:
{
19:
varbackgroundWorker=newBackgroundWorker();
20:
21:
backgroundWorker.WorkerSupportsCancellation=true;
22:
backgroundWorker.WorkerReportsProgress=true;
23:
24:
backgroundWorker.DoWork+=(s,e)=>
25:
{
26:
for(inti=0;i<10;i++)
27:
{
28:
System.Threading.Thread.Sleep(1000);
29:
_counter++;
30:
31:
backgroundWorker.ReportProgress(i*10,string.Format("ExecutetoNo.{0}",_counter.ToString()));
32:
}
33:
};
34:
35:
backgroundWorker.ProgressChanged+=(s,e)=>
36:
{
37:
CurrentProgress=e.ProgressPercentage;
38:
CurrentProgressText=e.UserState!
=null?
e.UserState.ToString():
String.Empty;
39:
};
40:
41:
backgroundWorker.RunWorkerCompleted+=(s,e)=>
42:
{
43:
CurrentProgress=100;
44:
CurrentProgressText="Completed!
";
45:
};
46:
47:
backgroundWorker.RunWorkerAsync();
48:
49:
}
50:
51:
privateboolCanStartTask(objectparam)
52:
{
53:
returntrue;
54:
}
55:
56:
privatestring_currentProgressText;
57:
publicstringCurrentProgressText
58:
{
59:
get{return_currentProgressText;}
60:
set
61:
{
62:
if(_currentProgressText!
=value)
63:
{
64:
_currentProgressText=value;
65:
66:
if(PropertyChanged!
=null)
67:
{
68:
PropertyChanged(this,newPropertyChangedEventArgs("CurrentProgressText"));
69:
}
70:
}
71:
}
72:
}
73:
74:
privatedouble_currentProgress;
75:
publicdoubleCurrentProgress
76:
{
77:
get{return_currentProgress;}
78:
set
79:
{
80:
if(_currentProgress!
=value)
81:
{
82:
_currentProgress=value;
83:
84:
if(PropertyChanged!
=null)
85:
{
86:
PropertyChanged(this,newPropertyChangedEventArgs("CurrentProgress"));
87:
}
88:
}
89:
}
90:
}
91:
92:
publiceventPropertyChangedEventHandlerPropertyChanged;
93:
94:
}
95:
96:
publicclassDelegateCommand:
ICommand
97:
{
98:
99:
///
100:
101:
///Occurswhenchangesoccurthataffectwhetherthecommandshouldexecute.
102:
103:
///
104:
105:
publiceventEventHandlerCanExecuteChanged;
106:
107:
108:
109:
Func
110:
111:
Action
112:
113:
boolcanExecuteCache;
114:
115:
116:
117:
///
118:
119:
///Initializesanewinstanceoftheclass.
120:
121:
///
122:
123:
///Theexecuteaction.
124:
125:
///Thecanexecute.
126:
127:
publicDelegateCommand(Action
128:
129:
Func
130:
{
131:
132:
this.executeAction=executeAction;
133:
134:
this.canExecute=canExecute;
135:
136:
}
137:
138:
139:
140:
#regionICommandMembers
141:
142:
///
143:
144:
///Definesthemethodthatdetermineswhetherthecommand
145:
146:
///canexecuteinitscurrentstate.
147:
148:
///
149:
150:
///
151:
152:
///Datausedbythecommand.
153:
154:
///Ifthecommanddoesnotrequiredatatobepassed,
155:
156:
///thisobjectcanbesettonull.
157:
158:
///
159:
160:
///
161:
162:
///trueifthiscommandcanbeexecuted;otherwise,false.
163:
164:
///
165:
166:
publicboolCanExecute(objectparameter)
167:
{
168:
169:
booltempCanExecute=canExecute(parameter);
170:
171:
172:
173:
if(canExecuteCache!
=tempCanExecute)
174:
{
175:
176:
canExecuteCache=tempCanExecute;
177:
178:
if(CanExecuteChanged!
=null)
179:
{
180:
181:
CanExecuteChanged(this,newEventArgs());
182:
183:
}
184:
185:
}
186:
187:
188:
189:
returncanExecuteCache;
190:
191:
}
192:
193:
194:
195:
///
196:
197:
///Definesthemethodtobecalledwhenthecommandisinvoked.
198:
199:
///
200:
201:
///
202:
203:
///Datausedbythecommand.
204:
205:
///Ifthecommanddoesnotrequiredatatobepassed,
206:
207:
///thisobjectcanbesettonull.
208:
209:
///
210:
211:
publicvoidExecute(objectparameter)
212:
{
213:
214:
executeAction(parameter);
215:
216:
}
217:
218:
#endregion
219:
220:
}
221:
}
View(Xaml.cs)代码:
1:
usingSystem.Windows.Controls;
2:
3:
namespaceBackgroundWorkerTest
4:
{
5:
publicpartialclassMainPage:
UserControl
6:
{
7:
publicMainPage()
8:
{
9:
InitializeComponent();
10:
11:
this.DataContext=newViewModel();
12:
}
13:
}
14:
}
View(Xaml)代码:
1:
Class="BackgroundWorkerTest.MainPage"
2:
xmlns="
3:
xmlns:
x="
4:
xmlns:
d="
5:
xmlns:
mc="http:
//schemas.openxmlformats.org/markup-compatibility/2006"
6:
mc:
Ignorable="d"
7:
d:
DesignHeight="300"d:
DesignWidth="400">
8:
9:
Name="LayoutRoot"Background="White">
10:
VerticalAlignment="Top"Width="87"Command="{BindingStartTaskCommand}"/>
11:
Text="{BindingCurrentProgressText}"VerticalAlignment="Top"Width="359"/>
12:
Margin="18,75,0,0"Name="progressBar1"VerticalAlignment="Top"Width="361"/>
13:
14:
Dispatcher
如果没有使用BackgroundWorker在非UI线程需要调用UI回调的时候,需要调用当前Application的Dispatcher来完成,比如:
1:
privatevoidUpdateUI()
2:
{
3:
Dispatcher.BeginInvoke(()=>
4:
{
5:
ProgressBar.Value=50;
6:
});
7:
}
如果你在一个Class里面(非UserControl),也就是无法获得Application对象的情况下,情况要负责一些,你可以使用一个假的控件对象来构造一个Dummy控件,例如:
1:
//以下代码在非UserControl的Class里面:
2:
TextBlock_dispatcherObject=newTextBlock();
3:
privatevoidUpdateUINasty()//avoidthisapproachunlessit'sallyou'vegot
4:
{
5:
_dispatcherObject.Dispatcher.BeginInvoke(()=>
6:
{
7:
SomePage.ProgressBar.Value=50;
8:
});
9:
}
反之,如果运行在UI线程里面,就不必像上面那样做,最好使用Deployment.Current.Dispatcher对象:
1:
privatevoidUpdateUINotSoNasty()
2:
{
3:
Deployment.Current.Dispatcher.BeginInvoke(()=>
4:
{
5:
SomePage.ProgressBar.Value=50;
6:
});
7:
}
当然,最保险的方法是先检查当前线程是否是UI线程,如果不是,那么进行UI操作需要用BeginInvoke:
1:
Actionmyaction=()=>DoSomething();
2:
vardispatch=Deployment.Current.Dispatcher;
3:
if(dispatch.CheckedAccess)
4:
{
5:
myaction();
6:
}
7:
else
8:
{
9:
dispatch.BeginInvoke(myaction());
10:
}
代码截图:
使用定时器:
DispatcherTimer
1:
privatevoidStartTimer()
2:
{
3:
DispatcherTimertimer=newDispatcherTimer();
4:
5:
timer.Tick+=(s,e)=>
6:
{
7:
//dosomeveryquickworkhere
8:
9:
//updatetheUI
10:
StatusText.Text=DateTime.Now.Second.ToString();
11:
};
12:
13:
timer.Interval=TimeSpan.FromSeconds
(1);
14:
timer.Start();
15:
}