使用Task简化Silverlight调用Wcf(续)
上一篇使用Task简化Silverlight调用Wcf介绍了Silverlight下使用Task的一些方法,这篇继续改进一下。
改进生成工具的生成的方法
上次生成的代码如下,这些TaskAsync只是简单的包装一下Wcf的begin和end方法:
1 2 3 4 5 6 7 8 | public Task DoWorkTaskAsync() { return Task.Factory.FromAsync( this .Channel.BeginDoWork, this .Channel.EndDoWork, null ); } public Task<DateTime> GetSerivceTimeTaskAsync() { return Task<DateTime>.Factory.FromAsync( this .Channel.BeginGetSerivceTime, this .Channel.EndGetSerivceTime, null ); } |
调用时需要手动去Wait():
1 2 3 4 5 6 7 8 9 10 11 12 | private void OnGetTimeClick( object sender, RoutedEventArgs e) { ThreadPool.QueueUserWorkItem(s => { var task = _systemServiceClient.GetSerivceTimeTaskAsync(); task.Wait(); Dispatcher.BeginInvoke(() => { MessageBox.Show(task.Result.ToString()); }); }); } |
这次生成的方法连task1.Wait(); 也包含了,多生成一个方法来Wait:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public Task DoWorkTaskAsync() { return Task.Factory.FromAsync( this .Channel.BeginDoWork, this .Channel.EndDoWork, null ); } public void DoWork() { var task = DoWorkTaskAsync(); task.Wait(); } public Task<DateTime> GetSerivceTimeTaskAsync() { return Task<DateTime>.Factory.FromAsync( this .Channel.BeginGetSerivceTime, this .Channel.EndGetSerivceTime, null ); } public DateTime GetSerivceTime() { var task = GetSerivceTimeTaskAsync(); task.Wait(); return task.Result; } |
这样调用包含Wait的方法就直接返回结果了,而不是返回Task,再去Wait():
1 2 3 4 5 6 7 8 | private void OnGetTimeClick( object sender, RoutedEventArgs e) { ThreadPool.QueueUserWorkItem(s => { var time = _systemServiceClient.GetSerivceTime(); Dispatcher.BeginInvoke(() => MessageBox.Show(time.ToString())); }); } |
UI同步技巧
调用Wcf和UI交互需要顺序进行是最平常的需求,这时需要与UI交互也有“同步”的能力。例如:
1 2 3 4 5 6 7 8 9 10 11 12 | ThreadPool.QueueUserWorkItem(s => { //调用Wcf var num = _systemServiceClient.GetNum(5); //UI对话框询问是否继续 var result = childWin.ShowSync(); if (result == false ) return ; var time = _systemServiceClient.GetSerivceTime(); ....... }); |
如果是UI线程的话是不可以这样阻塞的,然而这里是后台线程,阻塞也是没所谓的,所以可以使用下面的方法来阻塞线程,来模拟同步:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public partial class TestChildWindow : ChildWindow { private readonly ManualResetEvent _manualResetEvent; public TestChildWindow() { InitializeComponent(); _manualResetEvent = new ManualResetEvent( false ); Closed += (_, __) => _manualResetEvent.Set(); } public bool ? ShowSync() { if (Dispatcher.CheckAccess()) throw new InvalidOperationException( "ShowSync只能使用后台线程调用!" ); Dispatcher.BeginInvoke(Show); _manualResetEvent.Reset(); _manualResetEvent.WaitOne(); return DialogResult; } ......... } |
这里使用ManualResetEvent类来等待,打开窗体后马上阻塞,直到子窗体Closed时通知结束,实现”同步“。
这里注意ShowSync的Dispatcher.CheckAccess()判断,明确只能再后台线程里调用。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | private void OnMultiTaskClick( object sender, RoutedEventArgs e) { var childWin = new TestChildWindow(); ThreadPool.QueueUserWorkItem(s => { const string format = "Num:{1},{0}{2},{0}Time:{3},{0}UserCount:{4},{0}ChildWinResult:{5}" ; var num = _systemServiceClient.GetNum(5); var str = _systemServiceClient.SayHiTo(num.ToString()); //这里是“同步”的 var result = childWin.ShowSync(); var time = _systemServiceClient.GetSerivceTime(); var all = _userServiceClient.GetAll(); var msg = string .Format(format, Environment.NewLine, num, str, time, all.Count, result); Dispatcher.BeginInvoke(() => MessageBox.Show(msg)); }); } |

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库