当前位置:编程学习 > 网站相关 >>

我的WCF之旅(6):在Winform Application中调用Duplex Service出现TimeoutException的原因和

几个星期之前写了一篇关于如何通过WCF进行 双向通信的文章([原创]html" target=_blank>我的WCF之旅(3):在WCF中实现双向通信(Bi-directional Communication) ),在文章中我提供了一个如果在Console Application 调用Duplex WCF Service的Sample。前几天有个网友在上面留言说,在没有做任何改动得情况下,把 作为Client的Console Application 换成Winform Application,运行程序的时候总是出现Timeout的错误。我觉得这是一个很好的问题,通过这个问题,我们可以更加深入地理解WCF的消息交换的机制。
1.问题重现

首先我们来重现这个错误,在这里我只写WinForm的代码,其他的内容请参考我的文章。Client端的Proxy Class(DuplexCalculatorClient)的定义没有任何变化。我们先来定义用于执行回调操作(Callback)的类——CalculatorCallbackHandler.cs。代码很简单,就是通过Message Box的方式显示运算的结果。

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Artech.DuplexWCFService.Contract;
using System.ServiceModel;

namespace Artech. WCFService.Client
{
    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class CalculatorCallbackHandler : ICalculatorCallback
    {
        ICalculatorCallback Members#region ICalculatorCallback Members
        public void ShowResult(double x, double y, double result)
        {
            MessageBox.Show(string.Format("x + y = {2} where x = {0} and {1}", x, y, result),"Result", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        #endregion
    }
}

接着我们来设计我们的UI,很简单,无需多说。

\


代码如下


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace Artech. WCFService.Client
{
    public partial class Form1 : Form
    {
        private DuplexCalculatorClient _calculator;
        private double _op1;
        private double _op2;
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            this._calculator = new DuplexCalculatorClient(new System.ServiceModel.InstanceContext(new CalculatorCallbackHandler()));
        }
        private void Calculate()
        {
            this._calculator.Add(this._op1, this._op2);
        }
        private void buttonCalculate_Click(object sender, EventArgs e)
        {
            if (!double.TryParse(this.textBoxOp1.Text.Trim(), out this._op1))
            {
                MessageBox.Show("Please enter a valid number","Error", MessageBoxButtons.OK,  MessageBoxIcon.Error);
                this.textBoxOp1.Focus();
            }
            if (!double.TryParse(this.textBoxOp2.Text.Trim(), out this._op2))
            {
                MessageBox.Show("Please enter a valid number","Error", MessageBoxButtons.OK,  MessageBoxIcon.Error);
                this.textBoxOp1.Focus();
            }
            try
            {
                this.Calculate();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}

启动Host,然后随启动Client,在两个Textbox中输入数字2和3,Click Calculate按钮,随后整个UI被锁住,无法响应用户操作。一分后,出现下面的错误。

\


我们从上面的Screen Shot中可以看到这样一个很有意思的现象,运算结果被成功的显示,显示,但是有个Exception被抛出:”This request operation sent to http://localhost:6666/myClient/4f4ebfeb-5c84-45dc-92eb-689d631b337f did not receive a reply within the configured timeout (00:00:57.7300000). The time allotted to this operation may have been a portion of a longer timeout. This may be because the service is still processing the operation or because the service was unable to send a reply message. Please consider increasing the operation timeout (by casting the channel/proxy to IContextChannel and setting the OperationTimeout property) and ensure that the service is able to connect to the client.”。

2.原因分析

在我开始分析为什么会造成上面的情况之前,我要申明一点:由于找不到任何相关的资料,以下的结论是我从试验推导出来,我不能保证我的分析是合理的,因为有些细节我自己都还不能自圆其说,我将在后面提到。我希望有谁对此了解的人能够指出我的问题, 我将不胜感激。

我们先来看看整个调用过程的Message Exchange过程,通过前面相关的介绍,我们知道WCF可以采用三种不同的Message Exchange Pattern(MEP)——One-way,Request/Response,Duplex。其实从本质上讲,One-way,Request/Response是两种基本的MEP, Duplex可以看成是这两种MEP的组合——两个One-way,两个Request/Response或者是一个One-way和一个Request/Response。在定义Service Contract的时候,如果我们没有为某个Operation显式指定为One-way (IsOneWay = true), 那么默认采用Request/Response方式。我们现在的Sample就是由两个Request/Response MEP组成的Duplex MEP。

\

 


从上图中我们可以很清楚地看出真个Message Exchange过程,Client调用Duplex Calculator Service,Message先从Client传递到Service,Service执行Add操作,得到运算结果之后,从当前的Operati

补充:综合编程 , 其他综合 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,