如何异步调用WCF服务?

时间:2012-09-13 12:02:54

标签: c# wcf service asynchronous

我正在尝试将WCF服务实现为Windows服务。我想异步调用它,因为有些方法可能会运行几秒钟。以下misc。教程(例如来自MSDN)似乎并没有真正完成这项工作。我有一些工作,但从服务返回到客户端的数据不是我所期望的。服务器上服务的示例代码如下:

public interface ISomeService
{
    [OperationContract(AsyncPattern = true)]
    IAsnycResult BeginSomeMethod(string someString);

    Collection<string> EndSomeMethod(IAsnycResult asyncresult);
}

[...]

public SomeService : ISomeService
{
    public IAsyncResult BeginSomeMethod(AsyncCallback callback, object state)
    {
        // Do something...
        Collection collection = new Collection<string>{"Some Item", "Another Item"};
        return new CompletedAsyncResult<Collection<string>>(collection);
    }

    public Collection<string> EndSomeMethod(IAsyncResult asyncResult)
    {
        CompletedAsyncResult<Collection<string>> result = 
            asyncResult as CompletedAsyncResult<Collection<string>>;
        if(result != null)
        {
            return result.Data;
        }

        return result;
    }
}

我可以成功安装Windows服务,也可以通过浏览器调用它来查看WSDL。我还可以添加对我的“客户端”项目的引用来使用它 - 生成代理类等没有任何错误。我也可以这样称呼我的方法:

[...]
    object async = new object();
    someService.BeginSomeMethod( "Some string", EndSomeMethod, async );        
[...]

回调方法如下所示:

[...]
public static void EndSomeMethod( IAsyncResult asyncResult )
    CompletedAsnycResult<Collection<string>> result = 
        asyncResult as CompletedAsnycResult<Collection<string>>;
[...]

在此之后,结果为null(即转换不成功),asyncResult确实包含一些属性和数据,但不包含预期的(或想要的)字符串集合。

修改 我可以验证服务方法是否执行了它应该做的事情(例如,写入日志文件,创建文件或类似的东西)。 的 /修改

我已经尝试了几种方法,但是我对这里的错误感到有些困惑。 Microsoft提供的示例显然不正确(如某些MSDN页面上所述)。我还在事件处理程序等方面找到了一些其他建议,但这是现在最好的方法吗?

我是否真的必须使用OperationContract属性中的AsyncPattern = true来装饰服务方法?或者我可以使用VS2010的工具来生成异步调用方法的方法吗?

我知道有很多关于这个问题的问题,但是在这个问题上花了好几个小时之后我觉得很困难。

3 个答案:

答案 0 :(得分:2)

您需要在回调中调用someService.EndSomeMethod(asyncResult)以获取服务结果。这实际上是标准APM模式的一部分。说FileStream,你必须做同样的事情。

  

在此之后,结果为空

是的,因为CompletedAsnycResult仅存在于服务器上。您的客户端可以获取运行时返回的任何其他类型。 IAsyncResult不是WCF电汇合同的一部分。

实际上,asyncResult将是某个WCF内部类的实例。

答案 1 :(得分:1)

让我在这里粘贴我在WinForm .Net 4.0中使用的模式:

//Server WCF
public SomeService
{
    [OperationContract]
    Collection<string> SomeMethod(string someString)
    {
        return new Collection<string>{"Some Item", "Another Item"};
    }
}


//Client
void button_Click(object sender, EventArgs e)
{
    var someService = new TypedServiceReference();
    someService.BeginSomeMethod("Hello", this.someMethodEnded, someService);
}
//will be called once the server reply
void someMethodEnded(IAsyncResult r)
{
    this.Invoke(new MethodInvoker(delegate//The callback is not in the GUI thread
    {
        var someService = (TypedServiceReference) r.AsyncState;//it is the last argument of the BeginSomeMethod() call
        Collection<string> result = someService.EndSomeMethod(r);//Will raise server or network exception (if any)
        this.Text = result.First();
    }));
}

答案 2 :(得分:0)

你看过这个吗?:

wcf async processing

  

从你的例子来看,我认为你正在做所有的工作   在“开始”呼叫结束之前;这是我发现的一个常见错误   在学习异步模式时。

     

虽然我不熟悉它在WCF中的应用程序,Async模型   更典型的是一个Begin方法,用于启动一些新线程   IAsyncResult对象由该新线程更新。去完成”   动作,当IsCompleted设置为true时,原始调用者是   期望将原来的IAsyncResult对象传回给   返回结果的相应End方法。一件微不足道的事   实现如下: