2

我正在尝试将 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>>;
[...]

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

编辑 我可以验证服务方法是否完成了它应该做的事情(例如写入日志文件、创建文件或类似的东西)。 /编辑

我尝试了更多的方法,但我对我在这里做错了什么感到有些困惑。Microsoft 提供的示例显然不正确(如在某些 MSDN 页面上阅读的那样)。我还发现了一些有关事件处理程序等的其他建议,但这是现在最好的方法吗?

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

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

4

3 回答 3

2

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

在此之后,结果为空

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

在实践中,asyncResult将是一些 WCF 内部类的实例。

于 2012-09-13T12:24:14.313 回答
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();
    }));
}
于 2014-08-07T05:35:08.947 回答
0

你看过这个吗?:

wcf 异步处理

从您的示例来看,在我看来,您好像在“开始”调用完成之前完成了所有工作;这是我在学习异步模式时发现的一个常见错误。

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

于 2012-09-13T14:14:15.100 回答