异步方法执行

时间:2011-07-28 14:03:07

标签: c# wcf asynchronous

为什么不执行Begin和End方法,然后在服务接口中定义同步操作?

以下是文章末尾的示例: http://www.danrigsby.com/blog/index.php/2008/03/26/async-operations-in-wcf-iasyncresult-model-server-side/

我添加了一些调试信息:

public double GetSquareRoot(double value)
{
    System.Diagnostics.Debugger.Log(0, "MyService", "Get - Start\n");
    Thread.Sleep(3000);
    System.Diagnostics.Debugger.Log(0, "MyService", "Get - Finish\n");
    return Math.Sqrt(value);
}

public IAsyncResult BeginGetSquareRoot(double value, AsyncCallback callback, object     state)
{
    System.Diagnostics.Debugger.Log(0, "MyService", "Begin - Start\n");
    GetSquareRootAsyncResult asyncResult = new GetSquareRootAsyncResult(callback,     state);
    asyncResult.Value = value;
    ThreadPool.QueueUserWorkItem(new WaitCallback((Callback)), asyncResult);
    System.Diagnostics.Debugger.Log(0, "MyService", "Begin - Finish\n");
    return asyncResult;
}

public double EndGetSquareRoot(IAsyncResult asyncResult)
{
    System.Diagnostics.Debugger.Log(0, "MyService", "End - Start\n");
    double result = 0;
    using (GetSquareRootAsyncResult getSquareRootAsyncResult = asyncResult as      GetSquareRootAsyncResult)
    {
        getSquareRootAsyncResult.AsyncWaitHandle.WaitOne();
        result = getSquareRootAsyncResult.Result;
    }
    System.Diagnostics.Debugger.Log(0, "MyService", "End - Finish\n");
    return result;
}

对于原始代码,测试结果为:

  • 获取 - 开始
  • 获取 - 完成

然后我从IMyService中删除了GetSquareRoot方法,我得到了:

  • 开始 - 开始
  • 开始 - 完成
  • 回拨 - 开始
  • 获取 - 开始
  • 获取 - 完成
  • 回调 - 完成
  • 结束 - 开始
  • 结束 - 完成

是什么原因?

客户代码:

public partial class Form1 : Form
{
    IMyService m_Client;
    public Form1()
    {
        InitializeComponent();
        ChannelFactory<IMyService> factory = new ChannelFactory<IMyService>("netTcp");
        factory.Open();
        m_Client = factory.CreateChannel();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        double value = 0;
        Double.TryParse(m_ValueTextBox.Text, out value);
        m_Client.BeginGetSquareRoot(value, OnEndGetSquareRoot, null);
        m_StartButton.Enabled = false;
        m_ResultTextBox.Text = @"Loading...";
    }

    public void OnEndGetSquareRoot(IAsyncResult asyncResult)
    {
        this.Invoke(new MethodInvoker(delegate()
            {
                m_ResultTextBox.Text =                             
                    m_Client.EndGetSquareRoot(asyncResult).ToString();
                m_StartButton.Enabled = true;
            }));
    }
}

所描述案例的不同之处仅在于IMyService界面中没有声明GetSquareRoot。

2 个答案:

答案 0 :(得分:3)

我之前看过那篇文章,这是错的。您是IMyService合同接口的服务器端版本,根本不应该具有该方法的同步定义。 WCF调度程序运行时将始终选择通过异步方法将消息映射到同步方法定义。在这种情况下,您不会与客户端共享原始.NET服务合同接口,除非您还想强制客户端只能异步调用服务。

另外,请记住,客户端使用方法的异步版本这一事实对服务器端来说绝对没有任何意义。对于所有客户端都知道,它可能是在Linux的另一端运行的Java服务。客户端总是可以调用方法的同步或异步版本,但它看起来总是与服务端相同。

答案 1 :(得分:0)

你正在调用不同的方法。使用异步方法不实现同步方法。