<转>WCF中出现死锁或者超时
一、服务器端死锁
对于如下服务:
[ServiceContract(CallbackContract = typeof(INotify))]
public class DownloadService
{
[OperationContract]
public void Download()
{
//开始下载操作
//..... //通知下载完成
var callback = OperationContext.Current.GetCallbackChannel<INotify>();
callback.DownloadComplete();
}
} interface Inotify
{
[OperationContract]
void DownloadComplete();
}
首先我们用一个控制台程序作为客户端,代码如下:
class Program
{
static void Main(string[] args)
{
var context = new System.ServiceModel.InstanceContext(new CallBack());
var client = new DownloadServiceClient(context);
client.Download();
}
} class CallBack : DownloadServiceCallback
{
public void DownloadComplete()
{
Console.WriteLine("finished");
}
}
当运行这个程序时,会出现如下异常:
未经处理的异常: System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]: 此操作将死锁,因为在当前邮件完成处理以前无法收到答复。如果要允许无序的邮件处理,则在 ServiceBehaviorAttribute 上指定可重输入的或多个 ConcurrencyMode。
这个异常已经说得非常清楚了:当前服务不支持并发,在处理Download函数的时候信道是串行的,返回消息的时候必须先返回Download函数的处理消息,再返回DownloadComplete回调获取回调的返回结果;但Download函数本身又在等待DownloadComplete函数返回,从而形成了一个死锁。
这个异常同时也告诉了我们一个修改方案:修改服务的ServiceBehavior的ConcurrencyMode为Reentrant或Multiple即可。
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
public class DownloadService
实际上,这个问题还有另一种解决方案:如果无需等待回调完成,可以把回调函数设置为OneWay的方式;这样Download函数就不等待回调函数的返回结果了,不会因为互相等待而导致死锁。
interface Inotify
{
[OperationContract(IsOneWay=true)]
void DownloadComplete();
}
二、客户端死锁
由于系统自己能分析出服务器端的死锁,服务器端的死锁还是比较容易发现和处理的。但客户端的死锁就不是那么容易发现了。
经过前面的处理后,服务器端死锁问题已经解决了,客户端可以顺利处理了。这次我们把客户端代码放到WinForm版本的程序中,放在UI线程中处理。
private void button1_Click(object sender, EventArgs e)
{
var context = new System.ServiceModel.InstanceContext(new CallBack());
var client = new DownloadServiceClient(context);
client.Download();
}
当运行上述代码时,可以发现:点击按钮后,窗口就无响应了。由于此时没有任何错误提示信息,我就直接给出错误原因了:WCF的回调函数默认是在UI线程中执行,因此就会出现Download函数等待DownloadComplete回调执行完后才返回,而DownloadComplete回调又因为Download函数又等待着Download函数返回释放UI线程才能执行,这样又形成了一个死锁。而控制台程序没有UI线程,不会出现这种死锁。
对于这种死锁,根本的方案就是修改回调回调函数的通知线程,将其改为在非UI线程中执行。WCF中可以通过在客户端回调函数类中的CallbackBehaviorAttribute中控制这一行为
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = false)]
class CallBack : DownloadServiceCallback
我在这里还设置了CallbackBehaviorAttribute的ConcurrencyMode参数,这个参数在本例中是不必要的,但我还是习惯性的将其带上了,至于它在什么时候会用到,请读者朋友们自行分析。
<转>WCF中出现死锁或者超时的更多相关文章
- WCF初探-28:WCF中的并发
理解WCF中的并发机制 在对WCF并发机制进行理解时,必须对WCF初探-27:WCF中的实例化进行理解,因为WCF中的并发特点是伴随着服务实例上下文实现的.WCF的实例上下文模型可以通过Instanc ...
- SQLServer中的死锁的介绍
简介 什么是死锁? 我认为,死锁是由于两个对象在拥有一份资源的情况下申请另一份资源,而另一份资源恰好又是这两对象正持有的,导致两对象无法完成操作,且所持资源无法释放. 什么又是阻塞? 阻塞是 ...
- SQL Server中解决死锁
SQL Server中解决死锁的新方法介绍 数据库操作的死锁是不可避免的,本文并不打算讨论死锁如何产生,重点在于解决死锁,通过SQL Server 2005, 现在似乎有了一种新的解决办法. 将下面的 ...
- 重温WCF之WCF中可靠性会话(十四)
1.WCF中可靠性会话在绑定层保证消息只会被传输一次,并且保证消息之间的顺序.当使用TCP(Transmission Control Protocol,传输控制协议)通信时,协议本身保证了可靠性.然而 ...
- 我的WCF之旅(3):在WCF中实现双工通信
双工(Duplex)模式的消息交换方式体现在消息交换过程中,参与的双方均可以向对方发送消息.基于双工MEP消息交换可以看成是多个基本模式下(比如请求-回复模式和单项模式)消息交换的组合.双工MEP又具 ...
- 真实代理(RealProxy)在WCF中的运用
在WCF中,当我们在调用服务端的方法时,一般有两点需要考虑:1.捕获服务端的异常信息,记录日志:2.及时关闭会话信道,当调用超时或调用失败时及时中断会话信道.我们一般会像下面这样处理(以Calcula ...
- wcf 中客户端调用之死 感悟 wcf与原来的webservice2.0 的客户端调用区别(wcf调用完不关闭的话那就把web服务搞死了)
说到wcf,本人也是刚刚使用所以不是很熟悉 在做项目的时候采用webservice+客户端程序架构 写了一个wcf中的webservice之后,又写了很多的客户端exe程序,有的是轮询调用这个webs ...
- 在WCF中实现双工通信
双工(Duplex)模式的消息交换方式体现在消息交换过程中,参与的双方均可以向对方发送消息.基于双工MEP消息交换可以看成是多个基本模式下(比如请求-回复模式和单项模式)消息交换的组合.双工MEP又具 ...
- SQL Server中解决死锁的新方法介绍
SQL Server中解决死锁的新方法介绍 数据库操作的死锁是不可避免的,本文并不打算讨论死锁如何产生,重点在于解决死锁,通过SQL Server 2005, 现在似乎有了一种新的解决办法. 将下面的 ...
随机推荐
- 【Networking】容器网络大观 && SDN 资料汇总
SDNLAB技术分享(十五):容器网络大观 SDNLAB君• 16-06-17 •2957 人围观 编者按:本文系SDNLAB技术分享系列,本次分享来自SDN撕X群(群主:大猫猫)群直播,我们希望 ...
- Git的维护(git gc和git fsck)
原文: http://gitbook.liuhui998.com/4_10.html 一.保证git良好的性能 在大的仓库中, git靠压缩历史信息来节约磁盘和内存空间. 压缩操作并不是自动进行的, ...
- C# 复制(深拷贝、浅拷贝)
Object.MemberwiseClone 方法 创建当前 Object 的浅表副本. protected Object MemberwiseClone() MemberwiseClone 方法创建 ...
- C#之文本操作
[转载]C#文件操作大全(SamWang) 文件与文件夹操作主要用到以下几个类: 1.File类: 提供用于创建.复制.删除.移动和打开文件的静态方法,并协助创建 FileStream 对象. msd ...
- iOS GCD 必读推荐,有关于单例使用问题
链接如下:http://www.cocoachina.com/swift/20150129/11057.html 以前只注意使用dispatch_once达到创建单例对象时的线程安全,读了下边这篇文章 ...
- C# 对象实例几种方法
//实例方法1 //new CreateCalss cc1 = new CreateCalss(); //实例方法2 //获取当前程序集 Assembly asse = Assembly.GetExe ...
- MySQL binlog 组提交与 XA(分布式事务、两阶段提交)【转】
概念: XA(分布式事务)规范主要定义了(全局)事务管理器(TM: Transaction Manager)和(局部)资源管理器(RM: Resource Manager)之间的接口.XA为了实现分布 ...
- MySQL 主键范围查找问题
背景: 今天遇到一个主键范围查找的情况: id是主键,每次取10000.上面的这个查询id范围越往后面消耗的时间越久.通过id自增主键去查找数据应该不会出现这个现象的.以前都没有注意这个奇怪的现象,现 ...
- 关闭window 8.1 的skydrive
gpedit.msc-->计算机配置-->管理模板-->windows组件 -->skydrive-->阻止使用skydrive执行文件存储
- ASM:《X86汇编语言-从实模式到保护模式》第11章:进入保护模式
★PART1:进入保护模式 1. 全局描述符表(Global Descriptor Table,GDT) 32位保护模式下,如果要使用一个段,必须先登记,登记的信息包括段的起始地址,段的 ...