我正在尝试将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的工具来生成异步调用方法的方法吗?
我知道有很多关于这个问题的问题,但是在这个问题上花了好几个小时之后我觉得很困难。
答案 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模型 更典型的是一个Begin方法,用于启动一些新线程 IAsyncResult对象由该新线程更新。去完成” 动作,当IsCompleted设置为true时,原始调用者是 期望将原来的IAsyncResult对象传回给 返回结果的相应End方法。一件微不足道的事 实现如下: