一、服务器端死锁

对于如下服务:

 [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中出现死锁或者超时的更多相关文章

  1. WCF初探-28:WCF中的并发

    理解WCF中的并发机制 在对WCF并发机制进行理解时,必须对WCF初探-27:WCF中的实例化进行理解,因为WCF中的并发特点是伴随着服务实例上下文实现的.WCF的实例上下文模型可以通过Instanc ...

  2. SQLServer中的死锁的介绍

    简介      什么是死锁? 我认为,死锁是由于两个对象在拥有一份资源的情况下申请另一份资源,而另一份资源恰好又是这两对象正持有的,导致两对象无法完成操作,且所持资源无法释放. 什么又是阻塞? 阻塞是 ...

  3. SQL Server中解决死锁

    SQL Server中解决死锁的新方法介绍 数据库操作的死锁是不可避免的,本文并不打算讨论死锁如何产生,重点在于解决死锁,通过SQL Server 2005, 现在似乎有了一种新的解决办法. 将下面的 ...

  4. 重温WCF之WCF中可靠性会话(十四)

    1.WCF中可靠性会话在绑定层保证消息只会被传输一次,并且保证消息之间的顺序.当使用TCP(Transmission Control Protocol,传输控制协议)通信时,协议本身保证了可靠性.然而 ...

  5. 我的WCF之旅(3):在WCF中实现双工通信

    双工(Duplex)模式的消息交换方式体现在消息交换过程中,参与的双方均可以向对方发送消息.基于双工MEP消息交换可以看成是多个基本模式下(比如请求-回复模式和单项模式)消息交换的组合.双工MEP又具 ...

  6. 真实代理(RealProxy)在WCF中的运用

    在WCF中,当我们在调用服务端的方法时,一般有两点需要考虑:1.捕获服务端的异常信息,记录日志:2.及时关闭会话信道,当调用超时或调用失败时及时中断会话信道.我们一般会像下面这样处理(以Calcula ...

  7. wcf 中客户端调用之死 感悟 wcf与原来的webservice2.0 的客户端调用区别(wcf调用完不关闭的话那就把web服务搞死了)

    说到wcf,本人也是刚刚使用所以不是很熟悉 在做项目的时候采用webservice+客户端程序架构 写了一个wcf中的webservice之后,又写了很多的客户端exe程序,有的是轮询调用这个webs ...

  8. 在WCF中实现双工通信

    双工(Duplex)模式的消息交换方式体现在消息交换过程中,参与的双方均可以向对方发送消息.基于双工MEP消息交换可以看成是多个基本模式下(比如请求-回复模式和单项模式)消息交换的组合.双工MEP又具 ...

  9. SQL Server中解决死锁的新方法介绍

    SQL Server中解决死锁的新方法介绍 数据库操作的死锁是不可避免的,本文并不打算讨论死锁如何产生,重点在于解决死锁,通过SQL Server 2005, 现在似乎有了一种新的解决办法. 将下面的 ...

随机推荐

  1. PyQt4控件失去焦点和获得焦点

    #QListView控件多选设置self.ui.listView.setSelectionMode(QAbstractItemView.ExtendedSelection) #初始化QListView ...

  2. 火狐浏览器,关闭ssl v3防护

    某些网站,没有及时更新,导致火狐觉得有安全隐患,不给访问. --------------- Hello bcasey9090, go to about:config, copy the next bo ...

  3. PE355

    似乎我和lyx讨论过这题..? LP可解决..(~0.8s)

  4. phpcmsV9.5.8整合百度编辑器Ueditor1.4.3教程

    最近在搞phpcms视频功能,官方的视频功能实在是坑,刚开始是想将优酷的上传功能集成到ckeditor,在coding上有个项目,上传已经集成好了,还没有做上传后视频的获取和显示 项目地址:https ...

  5. MySQL 5.6 Threadpool(优先队列)介绍及性能测试【转】

    本文来自:http://www.gpfeng.com/?p=540&utm_source=tuicool&utm_medium=referral 背景介绍 MySQL常用(目前线上使用 ...

  6. Java for LeetCode 213 House Robber II

    Note: This is an extension of House Robber. After robbing those houses on that street, the thief has ...

  7. Ubuntu 14.04 下搭建SVN服务器 svn://

    Ubuntu 14.04 下搭建SVN服务器 svn:// 安装软件包: sudo apt-get install subversion 之后选择SVN服务文件及配置文件的放置位置.我放在了/srv下 ...

  8. replace和replaceAll(路径反斜杠问题)

    转载自:http://www.cnblogs.com/zhenmingliu/archive/2012/01/13/2321560.html 1)replace的参数是char和CharSequenc ...

  9. mac系统下如何解压.car文件

    纯手打: 1.去github下载demo然后运行  github地址:https://github.com/steventroughtonsmith/cartool 2.找到项目下cartool的位置 ...

  10. DX使用texconv工具批处理dds格式图片

    texconv D:\png\*.* -o E:\dds -m 5 -f dxt3 -ft dds 上述命令的意思是把D:\png目录下的全部文件(当然可以指定特定格式例如*.png)转换成dds格式 ...