转WCF中出现死锁或者超时

news/2024/7/4 9:22:59

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参数,这个参数在本例中是不必要的,但我还是习惯性的将其带上了,至于它在什么时候会用到,请读者朋友们自行分析。

转载于:https://www.cnblogs.com/chcong/p/4307910.html


http://www.niftyadmin.cn/n/2828933.html

相关文章

ConcurrentMultiMap 实现

2019独角兽企业重金招聘Python工程师标准>>> Index&#xff0c;akka用来存储对应dispatcher和actor的&#xff0c;也是Akka实现的ConcurrentMultiMap<K,V> key类型自定义&#xff0c;value是由ConcurrentSkipListSet构成的,内部其实就对ConcurrentMultiMap<…

GPS机制分析(5)

1. 概述 ​ 上面的几篇文章论述了gps的打开启动初始化等动作,万事俱备只欠东风了。这一系列文章主要讲的是Position信息如何从modem层传递到loc eng层最后一直到Java上层的。由于loc eng层到modem层是属于消息触发的&#xff0c;也就是说正常的流程是&#xff1a;modem层传上来…

GPS机制分析(6)

7. gps数据从HAL传输到Java ​ 上面UlpLocation类型的mLocation作为参数传入&#xff0c;这里传递的还是UlpLocation类型的数据&#xff0c;不是hal层使用的GpsLocation类型&#xff0c;因此我们看一下UlpLocation类型的数据转换成GpsLocation类型的数据的过程&#xff1a; h…

IPC—Android Binder (1)

IPC是Inter-Process Communication的缩写&#xff0c;含义就是跨进程通信。 多进程场景 WebView加载图片推送 原因 内存不够->内存就够了 App运行独立的虚拟机——每个进程分配运行内存是有限的——32M、64M、48M 加载一个大图片——直接OOM 如果一旦奔溃&#xff0c;…

AndroidGPS定位应用流程

AndroidGPS定位应用流程 这里先了解下应用层流程。 根据这个框架&#xff0c;GPS在应用层实现的最基本流程示例&#xff1a; public class MainActivity extends Activity {private LocationManager mLocationManager;Overrideprotected void onDestroy() {super.onDestroy…

怎么把照片做成消消乐_开心消消乐特效制作如何快速的消除过关

开心消消乐特效制作如何快速的消除过关。在闯关的时候&#xff0c;我们想要制作三星过关&#xff0c;特效的制作是我们必须的过程。如果没有特效帮助我们大量的消除&#xff0c;想要得到3星的分数是比较困难的。但是在释放特效的时候&#xff0c;我们是需要一定的技巧的。单独的…

debian卸载php_在 Ubuntu/Debian 下安装 PHP7.3 教程

介绍最近的 PHP 7.3.0 已经在 2018 年12月6日 发布 GA&#xff0c;大家已经可以开始第一时间体验新版本了&#xff0c;这里先放出 PHP7.3 安装的教程以便大家升级。适用系统&#xff1a; Ubuntu 18.04 LTS / Ubuntu 16.04 LTS &#xff0f; Ubuntu 14.04 LTS / Debian 9 stretc…