异步WCF调用在单卡在无限循环
本文关键字:单卡 无限循环 调用 WCF 异步 | 更新日期: 2023-09-27 18:08:13
我有一个问题在MonoAndroid调用WCF服务异步。我按照本教程创建了便携式类库。http://nullskull.com/a/10476775/xamarin -交叉平台-应用程序-使用wcf - - 1.部分aspx
这是我调用WCF服务的服务方法:
public async static Task<KeyExchangeModel> GetPublicKeyFromServer(KeyExchangeModel model)
{
try
{
ISyncService client;
client = new SyncServiceClient(_binding, _endpointAddress);
var res = Task<KeyExchangeModel>.Factory.FromAsync(client.BeginGetServerPublicKey, client.EndGetServerPublicKey,
model, null);
await res;
return res.Result;
}
catch (Exception e)
{
return null;
}
}
在这里我调用方法并等待直到它被执行。
Task<KeyExchangeModel> task = SyncServiceAgent.GetPublicKeyFromServer(keyModel);
task.Wait();
KeyExchangeModel serverModel = task.Result;
问题是,在Android上我从来没有得到的结果。它陷入了一个循环。没有异常记录在设备日志中或被抛出。
此代码在Windows单元测试和Windows Phone项目上完美工作。
我希望任何人都能帮助我。
你的问题是这一行:task.Wait();
阻塞异步代码会导致死锁。
默认情况下,await
将捕获当前的"上下文",并使用该上下文来恢复async
方法。在这种情况下,它可能会捕获UI上下文,它绑定到UI线程。因此,GetPublicKeyFromServer
将启动WCF调用,捕获UI上下文,并返回一个未完成的任务。然后调用代码在该任务上调用Task.Wait
,该阻塞 UI线程,直到异步方法完成。
之后,WCF调用返回,GetPublicKeyFromServer
尝试在相同的上下文中(在UI线程上)恢复。然而,UI线程被阻塞,等待GetPublicKeyFromServer
完成。这是一个典型的死锁情况。
它在单元测试中工作的原因是因为async
方法捕获线程池上下文而不是UI上下文,因此它能够阻塞Wait
中的一个线程池线程,而另一个线程池线程可以完成async
方法。通常情况下,Windows Phone应用程序会有与Android应用程序相同的UI上下文问题,所以我怀疑测试代码有不同的地方,这就是为什么它没有在WP上死锁。
我在我的博客、MSDN的一篇文章和我的书中更详细地描述了这个问题。
此问题的最佳解决方案是使用await
而不是Task.Wait
或Task<T>.Result
。也就是说,你的调用代码应该是:
Task<KeyExchangeModel> task = SyncServiceAgent.GetPublicKeyFromServer(keyModel);
KeyExchangeModel serverModel = await task;
这将要求您的调用代码为async
,这反过来要求其调用者为async
,等等。这种async在代码库中的"增长"是自然和正常的。