【发布时间】:2011-02-25 01:37:41
【问题描述】:
我正在尝试重用一些对数据访问层类型服务执行某些调用的 .NET 代码。我已经设法将方法的输入和方法的输出都打包了,但不幸的是,服务是从内部代码调用的,我真的不想为了异步而重写。
不幸的是,Silverlight 中生成的 web 服务代码只生成异步方法,所以我想知道是否有人有工作代码可以解决这个问题?
注意:我不需要在 UI 线程上执行主代码路径,但有问题的代码会期望它对数据访问层的调用本质上是同步的,但整个作业可以主要在后台线程上执行。
我尝试了此处找到的方法:The Easy Way To Synchronously Call WCF Services In Silverlight,但不幸的是它超时并且从未完成调用。
或者更确切地说,似乎发生的是调用完成的事件处理程序,但仅在方法返回之后。我怀疑事件处理程序是从调度程序或类似程序调用的,并且由于我在这里阻塞了主线程,所以它永远不会完成,直到代码真正回到 GUI 循环中。
或者类似的东西。
这是我在找到上述配方之前写的自己的版本,但它遇到了同样的问题:
public static object ExecuteRequestOnServer(Type dalInterfaceType, string methodName, object[] arguments)
{
string securityToken = "DUMMYTOKEN";
string input = "DUMMYINPUT";
object result = null;
Exception resultException = null;
object evtLock = new object();
var evt = new System.Threading.ManualResetEvent(false);
try
{
var client = new MinGatServices.DataAccessLayerServiceSoapClient();
client.ExecuteRequestCompleted += (s, e) =>
{
resultException = e.Error;
result = e.Result;
lock (evtLock)
{
if (evt != null)
evt.Set();
}
};
client.ExecuteRequestAsync(securityToken, input);
try
{
var didComplete = evt.WaitOne(10000);
if (!didComplete)
throw new TimeoutException("A data access layer web service request timed out (" + dalInterfaceType.Name + "." + methodName + ")");
}
finally
{
client.CloseAsync();
}
}
finally
{
lock (evtLock)
{
evt.Close();
evt = null;
}
}
if (resultException != null)
throw resultException;
else
return result;
}
基本上,这两种食谱都是这样做的:
- 设置 ManualResetEvent
- 挂钩已完成的事件
- 事件处理程序从服务调用中获取结果,并向事件发出信号
- 主线程现在异步启动 Web 服务调用
- 然后等待事件发出信号
但是,在上述方法返回之前,不会调用事件处理程序,因此我的代码会检查 evt != null 等,以避免在方法超时后 TargetInvocationException 杀死我的程序。
有谁知道:
- ...如果在 Silverlight 3 中可能的话
- ...我在上面做错了什么?
【问题讨论】: