【问题标题】:How can I asynchronously call a WCF service?如何异步调用 WCF 服务?
【发布时间】:2012-09-13 12:02:53
【问题描述】:

我正在尝试将 WCF 服务实现为 Windows 服务。我想异步调用它,因为有些方法可能会运行几秒钟。以下杂项。教程(例如来自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 的工具来生成异步调用方法的方法吗?

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

【问题讨论】:

    标签: c# wcf service asynchronous


    【解决方案1】:

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

    在此之后,结果为空

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

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

    【讨论】:

    • 是否有一个页面提供具有标准实践的工作教程?有太多页面(恕我直言)过时的代码示例。如果有一个包含(服务器)服务代码和作为消费者的客户端的示例,那就太好了。好像两边都有回调,这是不对的吗?
    • 首先请注意,服务器和客户端是 100% 独立的。您可以在双方独立使用同步或异步(如果您不完全了解这一点,请告诉我)。事实上,我很难找到我喜欢的单个代码示例。您可能想在此处查看 FileStream.BeginRead 示例:msdn.microsoft.com/en-us/library/zxt5ahzw.aspx 异步文件 IO 就像异步 Web 服务 IO 一样工作。这也可能会有所帮助:msdn.microsoft.com/en-us/library/ms228963.aspx(深入研究子主题)。
    • 是的,这是我遇到的问题之一 - 我可以在服务器上使用 [OperationContract(AsyncPattern = true)],但我也可以说(在 VS2010 中)我想要它创建/配置服务引用时“生成异步操作”。我会查看你的链接,看看我是否会得到一个简单的例子来工作并返回我的发现。
    • 是的,对于从客户端异步调用,您需要“生成异步操作”。服务器所做的对客户端来说并不重要,因为重要的是有线协议(SOAP over HTTP)。服务器内部被抽象掉了。
    • 那么使用它们有什么好处呢?当客户端可以异步处理对同步服务器方法的请求时,我为什么要将服务器上的相应操作实现为异步操作?
    【解决方案2】:

    让我在这里粘贴我在 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();
        }));
    }
    

    【讨论】:

      【解决方案3】:

      你看过这个吗?:

      wcf async processing

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

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

      【讨论】:

      • 是的,我做到了,但我会再次以全新的心态,我可能一直处于混乱状态......
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-04
      • 2012-10-03
      • 2010-09-28
      • 1970-01-01
      • 2020-01-21
      • 2018-09-07
      相关资源
      最近更新 更多