使用Task简化Silverlight调用Wcf
原文 http://www.cnblogs.com/lemontea/archive/2012/12/09/2810549.html
从.Net4.0开始,.Net提供了一个Task类来封装一个异步操作,用来简化异步 方法的调用。.Net4.5更进一步,添加了async和await两个关键字,异步编程同步化,不用再写一堆散乱的回调或者完成事件处理。 Silverlight5开始支持Task类,但是要用await的话就需要编译器的支持,VS2012直接支持,如果是VS2010,那就要安装Async CTP,而Silverlight4没有Task类,但安装Async CTP后,得到的AsyncCtpLibrary_Silverlight.dll会带有适合Silverlight4使用的Task类。下面介绍怎么使用。
使用Task封装异步方法
可 能大家都知道,Task不是一个静态的工具类,我们不是调用它的一个静态方法来简化异步的调用,而是首先要将异步操作封装到一个Task中,然后再使用这 个封装好的Task,一个Task就包含了开始和回调(或者是开始和完成事件处理),这样对于Task的消费者来说,异步操作的复杂性就隐藏在Task的 背后了。TaskFactory<TResult>类能帮助我们快速封装异步方法到一个Task中。例如:
public Task<UserInfo> CreateUserTaskAsync(UserInfo user) {return Task<UserInfo>.Factory.FromAsync(this.Channel.BeginCreateUser, this.Channel.EndCreateUser, user, null); }
对于Wcf服务的方法,我暂时发现微软提供了两种方式自动生成这些基于Task方法。
1.VS2012+.Net4.5
VS2012下.Net4.5的项目在添加服务引用时有如下设置可以生成基于Task的方法
生成后的XXXAsync方法的返回类型就是Task<T>。例如:
public System.Threading.Tasks.Task<string> SayHelloToAsync(string name) {return base.Channel.SayHelloToAsync(name); }
2.Net4.0+TaskWsdlImportExtension.dll
如果使用VS2010或者在2012下的项目的目标框架是.Net4.0的话,是没有上面那个选项的。这时可以借助安装Async CTP后得到的TaskWsdlImportExtension.dll来帮助生成。首先对应的项目中引用 TaskWsdlImportExtension.dll,然后在web.config中添加如下配置:
<system.serviceModel> <client> <metadata><wsdlImporters><extension type="TaskWsdlImportExtension.TaskAsyncWsdlImportExtension, TaskWsdlImportExtension" /></wsdlImporters></metadata></client> </system.serviceModel>
更新服务引用后,同样得到基于Task的异步方法。
很可惜的是这个dll不适合Silverlight使用,所以我参考TaskWsdlImportExtension的封装方式(使用Task.Factory.FromAsync),自己做了个小工具来生成这些方法。
自定义工具生成Silverlight项目的基于Task的操作
这个工具本来想写成T4模版的,但对T4不是很熟,最后写成了一个exe。
大概原理如下,首先遍历项目下的所有叫Reference.cs的文件,动态把它编译为Assembly,再反射这个Assembly,找那些BeginXXX方法,把这些方法封装为Task方法放到一个跟原Service同命名空间,同一一个Client的部分类中。
使用方式可能有点麻烦,但个人认为可以接受。
1.在有服务引用的Silverlight类库中添加一个类
2.右键这个类,选择打开方式,添加,选择小工具的exe
然后确定,即可生成一堆XXXTaskAsync方法。
当然,上面是第一次使用,以后使用时,打开方式上存在这个程序,只需右击打开方式,再在列表选择这个程序两步即可。
生成的代码大概如下:
下面再看看怎么使用这些方法。
1.使用async和await
Silverlight项目使用vs2012或者VS2010安装了Async CTP的话,就可以使用async和await。
1.vs2010的话首先在在Async CTP下找到AsyncCtpLibrary_Silverlight.dll或者AsyncCtpLibrary_Silverlight5.dll,并添加引用
vs2012就在Nuget里搜索await,引用下面的这个包
1.普通使用
await的使用方式可能大家都知道,就不详细介绍,就是在方法里加async关键字,在Task方法前加await关键字
async private void OnMainPageLoaded(object sender, RoutedEventArgs e) {var users = await userServiceClient.GetAllTaskAsync();dataGrid1.ItemsSource = users; }
async private void OnMultiTaskClick(object sender, RoutedEventArgs e) {var num = await systemServiceClient.GetNumTaskAsync(3);var result = await systemServiceClient.SayHiToTaskAsync(num.ToString("n2"));var time = await systemServiceClient.GetSerivceTimeTaskAsync();var users = await userServiceClient.GetAllTaskAsync();MessageBox.Show(string.Format("Num:{1},{0}{2},{0}Time:{3},{0}UserCount:{4}", Environment.NewLine,num.ToString("n2"),result,time.ToString(),users.Count.ToString())); }
可以看到OnMultiTaskClick的第二个wcf方法是依赖于第一个wcf方法的结果的,这里感觉完全是”同步编程“,结果没有问题:
2.Debug
使用await做Debug时跟同步编程一样,无论单步或是其它,得心应手:
3.异常
调用wcf时产生的异常信息也跟不使用Task时一样的,对于Wcf返回来的异常类型是FaultException<ExceptionDetail>。把null传到下面这个方法产生的异常信息。
[OperationContract] public string SayHiTo(string name) {if (string.IsNullOrWhiteSpace(name))throw new ArgumentNullException("name");return string.Format("Hi,{0}!", name); }
2.后台线程+Task.Wait
如果没有VS2012或者不想安装Async CTP的话,就可以使用这种方式。由于Task.Wait是会阻塞线程的,在Silverlight的主线程是不允许这样做的,所以把操作放到后台线程去 做,既然是后台线程,所以就会存在跨线程操作UI的问题,要记得使用Dispatcher.BeginInvoke来操作UI。
1.普通使用
private void OnMainPageLoaded(object sender, RoutedEventArgs e) {ThreadPool.QueueUserWorkItem((s) =>{var task = userServiceClient.GetAllTaskAsync();task.Wait();Dispatcher.BeginInvoke(() =>{dataGrid1.ItemsSource = task.Result;});}); }
private void OnMultiTaskClick(object sender, RoutedEventArgs e) {ThreadPool.QueueUserWorkItem((s) =>{var task1 = systemServiceClient.GetNumTaskAsync(5);task1.Wait();var task2 = systemServiceClient.SayHiToTaskAsync(task1.Result.ToString());var task3 = systemServiceClient.GetSerivceTimeTaskAsync();var task4 = userServiceClient.GetAllTaskAsync();task2.Wait();task3.Wait();task4.Wait();Dispatcher.BeginInvoke(() =>{MessageBox.Show(string.Format("Num:{1},{0}{2},{0}Time:{3},{0}UserCount:{4}", Environment.NewLine,task1.Result.ToString(), task2.Result, task3.Result.ToString(), task4.Result.Count.ToString()));});}); }
跟上面一样,OnMultiTaskClick的第二个方法依赖于第一个方法,结果雷同。
这种方法感觉没有上面的await那么好,但也比直接编写的APM(Begin/End)或者EAP(完成事件)要方便不少。
2.Debug
使用这种方式Debug时要把断点放到委托内,其它一样,Wait后得到结果。
3.异常
这里调用wcf产生的异常有点不一样,原本的异常变成了AggregateException,而真正的FaultException<ExceptionDetail>跑到了InnerException里去了
使用这个方式还有一点要注意,调用wcf的产生异常跳到Application_UnhandledException时也是后台线程,需要使用Deployment.Current.Dispatcher.BeginInvoke来操作UI,例如:
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) {var msgFormat = "Message:{0} {1} StackTrace:{2}";var msg = e.ExceptionObject.Message;var stackTrace = e.ExceptionObject.StackTrace;if (e.ExceptionObject.InnerException != null && e.ExceptionObject.InnerException is FaultException<ExceptionDetail>){var ex = e.ExceptionObject.InnerException as FaultException<ExceptionDetail>;msg = ex.Detail.Message;stackTrace = ex.Detail.StackTrace;} Deployment.Current.Dispatcher.BeginInvoke(() =>{MessageBox.Show(string.Format(msgFormat, msg, System.Environment.NewLine, stackTrace));});e.Handled = true; }
总结
1.对于生成Task方法的方式,如果是.Net项目可以选择微软提供的方法,VS2012+.Net4.5直接在服务引用生成,其它使用TaskWsdlImportExtension.dll。
2.对于Silverlight项目的话,只能自己制造工具去包装了。
3.条件满足的话尽量使用await的方式来使用Task(VS2012或者VS2010+Async CTP)
4.使用VS2010又不想安装Async CTP就用后台线程+Task.Wait的方式,多注意后台线程不能调用UI的问题和异常处理的一点差异。
工具源码+测试Task测试代码
转载于:https://www.cnblogs.com/lonelyxmas/p/3278661.html
使用Task简化Silverlight调用Wcf相关推荐
- 看看async,await 是如何简化异步的调用WCF!
A:调用WCF难吗? B:不难 A:异步调用WCF难吗? B:不难, A:异步的调用WCF,并且需要保证异步的调用顺序难吗? B:不难 A:那什么难? B:异步的调用WCF,并且保证几个异步的调用顺序 ...
- [转]Silverlight在调用wcf时传输数据过大返回Not Found的解决办法
原文地址:http://www.cnblogs.com/gavinyao/archive/2012/04/17/2454495.html Silverlight在调用wcf时传输数据过大返回Not F ...
- Silverlight同步(Synchro“.NET研究”nous)调用WCF服务
Silverlight的RIA应用中访问远端的WebService或WCF服务,都是通过异步线程模式调用的.在某些情况下我们的调用是需要同步进行,虽然Silverlight没有内置同步线程模式调用远端 ...
- linux c调用wcf服务,Silverlight+WCF实现跨域调用
在这篇文章中,WCF扮演服务器,向外提供LoginVaild服务:Silverlight扮演客户端,调用WCF提供的LoginVaild服务.思路有了,下面进行代码实现. 数据库脚本实现 新建T_Us ...
- Silverlight在调用wcf时传输数据过大返回Not Found的解决办法
默认情况下,silverlight在调用wcf时,如果传递的数据中XML的Element的内容长度大于8192字节,即8k,会提示Not Found错误. 调用含有byte[]的方法时,内容长度大于1 ...
- Silverlight与WCF之间的通信(4)silverlight以net.tcp方式调用console上寄宿的wcf服务
(由于最近是针对一个demo进行的研究,在之前公开过代码结构,这里只是对需要改动的地方加以说明) WCF4.0使得编写wcf服务不再那么复杂,去掉了许多的配置信息,客户端只需要一个服务地址,便可在系统 ...
- WCF 入门之旅(4): 怎样用客户端调用WCF服务
WCF 入门之旅(4): 怎样用客户端调用WCF服务 前面的demo已经能够跑起来,现在开始考虑用客户端来测试所写的应用了,首先用个普通的应用程序来调用所写的wcf服务吧.其实最后运行wcf服务后的页 ...
- Silverlight 应用 WCF RIA Services 在 IIS6 部署问题总结
WCF RIA Services 部署在IIS6很简单,但是也会出现一些问题 我们的应用是Silverlight 4 Business Application,应用了WCF RIA Service, ...
- ArcGIS API for Silverlight 调用GP服务准备---GP模型建立、发布、测试
ArcGIS API for Silverlight 调用GP服务准备---GP模型建立.发布.测试 原文:ArcGIS API for Silverlight 调用GP服务准备---GP模型建立.发 ...
最新文章
- 每日一皮:这年头没点绝活连洗车都不行...
- 吴恩达机器学习笔记7-数据绘制
- HD 1003 Max Sum (最大字段和问题)
- vivado环境下实现比较器
- dhrystone测试结果_RTThread软件包可以对MCU进行性能测试,跑一个试试!
- 抖音计算机音乐你要我,抖音你要我怎么做是什么歌 抖音你要我怎么做怎么说才能爱我歌曲介绍...
- 监督学习-KNN最邻近分类算法
- sql statements_Postgresql监控sql模块之pg_stat_statements模块--部署篇
- centos7开放端口访问不了_CentOS7搭建GateOne,实现WebSSH
- 2021 年 4 月程序员工资统计,这太可怕了……
- python安装后桌面没有显示图标_Win10安装软件后找不到软件图标如何解决
- 读书06《简约至上》
- 【Java基础】· Java基本语法:程序流程控制习题总结
- word中如何在方框中打钩
- Pr:Lumetri颜色面板
- 习惯七 不断更新---平衡的自我提升原则
- LINUX下USB1.1设备学习小记(5)_uhci与设备(2)
- ue4 Authority和server的区别
- 魅族pro7plus android10,魅族PRO7和PRO7 Plus有什么区别?哪个好?一文秒懂
- USB HID键盘实现全键无冲解析