原文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测试代码

使用Task简化Silverlight调用Wcf的更多相关文章

  1. Silverlight调用一般性处理程序模拟Silverlight调用WCF效果(2)

    [置顶] Silverlight调用一般性处理程序模拟Silverlight调用WCF效果(2) 分类: 技术2012-03-31 12:51 548人阅读 评论(0) 收藏 举报 silverlig ...

  2. Silverlight调用WCF(1)

    [置顶] Silverlight调用WCF(1) 分类: 技术2012-03-31 12:29 940人阅读 评论(0) 收藏 举报 wcfsilverlightexceptionusersecuri ...

  3. Silverlight客户端调用WCF服务难题解疑

    一:解决办法 Silverlight客户端调用WCF服务在实际使用中经常会出现的问题就是无法直接应用类文件和配置文件.微软针对这一情况已经给出了解决办法.WCF开发框架可以帮助我们实现可靠性较高的跨平 ...

  4. 【Win 10应用开发】手动调用WCF服务

    调用服务最简单的方法就是,直接在VS里面添加服务引用,输入服务的地址即可,无论是普通Web服务,还是WCF服务均可.VS会根据获取到的元数据,自动生成客户端代码. 如果服务的调用量很大,应用广泛,可以 ...

  5. WCF基础教程之开篇:创建、测试和调用WCF

    一转眼,又半个月没有更新博客了.说实话,最近确实是有点忙.不过即使再忙忙,也要抽空来学习一些东西.最近用WCF比较多,就来跟大家分享一下关于WCF的知识吧!为了让大家都能看懂,照顾一些没有学过WCF的 ...

  6. ArcGIS API for Silverlight 调用GP服务准备---GP模型建立、发布、测试

    原文:ArcGIS API for Silverlight 调用GP服务准备---GP模型建立.发布.测试 第一篇.GP降雨量等值线建模.发布及测试 在水利.气象等行业中,要在WebGIS中实现空间分 ...

  7. silverlight与wcf双向通讯 例子

    本文将建立一个silverlight与wcf双向通讯的简单实例,以下是详细步骤: 新建Silverlight应用程序,名称WCFtest.解决方案中添加WCF服务应用程序,名称WcfServiceTe ...

  8. 多线程编程学习笔记——异步调用WCF服务

    接上文 多线程编程学习笔记——使用异步IO 接上文 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端 接上文 多线程编程学习笔记——异步操作数据库 本示例描述了如何创建一个WCF服务,并宿主 ...

  9. 抛弃WebService,在.NET4中用 jQuery 调用 WCF

    在我们之前的开发中,对于ajax程序,都是通过jQuery调用标记为[System.Web.Script.Services.ScriptService]的WebService,然后在WebServic ...

随机推荐

  1. JVM虚拟机选项:Xms Xmx PermSize MaxPermSize区别

    java虽然是自动回收内存,但是应用程序,尤其服务器程序最好根据业务情况指明内存分配限制.否则可能导致应用程序宕掉. 举例说明含义:-Xms128m 表示JVM Heap(堆内存)最小尺寸128MB, ...

  2. vi常用操作命令

    进入vi的命令 vi filename :打开或新建文件,并将光标置于第一行首 vi +n filename :打开文件,并将光标置于第n行首 vi + filename :打开文件,并将光标置于最后 ...

  3. mac git 命令提示

    直接进入正题: $ brew list 查看你是否已经安装了"bash-completion",如果没有,继续往下看: $ brew install bash-completion ...

  4. url&视图

    django.cof.url.defaults django.cof.url.defaults.patterns() 1 2 3 4 5 6 7 urlpatterns = patterns('', ...

  5. python cmd模块练习

    # encoding=utf-8 import cmd import sys # cmd模块练习 class Client(cmd.Cmd): ''' 1)cmdloop():类似与Tkinter的m ...

  6. Wordpress 音频播放器 Wordpress audio player with jQuery audioplayer.swf

    原文地址:http://justcoding.iteye.com/blog/545978 Wordpress audio player with jQuery How to use Wordpress ...

  7. 高龄“潮男”优衣库老板柳井正_榜样_奢华主义_YOKA时尚网

    高龄"潮男"优衣库老板柳井正_榜样_奢华主义_YOKA时尚网 高龄"潮男"优衣库老板柳井正

  8. #include <hash_set>

    哈希查找,不需要排序,适用于精确查找,比二分查找更快 #define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS #include <iostream&g ...

  9. Hibernate征途(一)之初识

    相见恨晚 很久以前,大概从开始接触数据库开始,就闪过这样一个想法,怎么看怎么觉得数据库表和vb的类模块很像,不是么?除了vb类模块还有函数外:越往下学觉得二者越像,尤其在三层时学到实体类的概念,我去, ...

  10. 【泛化物品】【HDU1712】【ACboy needs your help】

    ACboy needs your help Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...