【发布时间】:2017-06-02 13:42:39
【问题描述】:
我正在尝试编写一个使用 Task 和 TaskCompletion 的函数。
我的问题是登录后没有返回结果。我之前使用过类似的代码,它正在工作。我不知道造成这种情况的原因。
public async Task<byte[]> Sign(byte[] documentContent)
{
var service = new SignServiceWrapper("https://example.com?wsdl");
var loginResult = await Task.Run(() => service.Login(loginRequest));
//....
}
还有我的 SignServiceWrapper 类
public class SignServiceWrapper
{
private static string _webServiceUrl;
private BrokerClientClient client;
public SignServiceWrapper(string webServiceUrl)
{
_webServiceUrl = webServiceUrl;
}
public Task<loginResponse> Login(loginRequest request)
{
var tcs = new TaskCompletionSource<loginResponse>();
ClientGenerator.WebServiceUrl = _webServiceUrl;
ClientGenerator.InitializeService();
client = ClientGenerator.ServiceClient;
client.loginCompleted += (sender, loginResult) =>
{
if (loginResult.Error != null)
tcs.SetException(loginResult.Error);
else
tcs.TrySetResult(loginResult.Result);
};
client.loginAsync(request);
return tcs.Task;
}
// ...
}
如果我这样调用我的登录函数,它会起作用
var loginResult = Task.Run(() => service.Login(loginRequest));
loginResult.Wait();
我知道有一种死锁,但我不知道如何在这里解决这个问题以及哪个对象。
【问题讨论】:
-
您等待任务完成多长时间了?您是否尝试过单步执行任务以确保它正在处理?
-
我在 loginCompleted 事件中放了一个断点,结果出现了,但问题是它没有返回
-
await没有损坏。您的代码虽然很不寻常 - Task.Run and TCS and Web 服务调用,已经有loginAsync方法?你为什么不删除 整个Login方法并调用var response=await client.loginAsync(request);? -
请注意,使用
Task.Run然后在其中进行阻塞调用会导致假异步。 WCF 的异步方法根本不使用线程。 Windows IO 实际上在内核级别是异步的,通过模拟阻塞来简化编程。在阻塞方法之上使用Task.Run会浪费后台线程。使用 WCF 代理的 Async 或 Begin/End 方法不会 -
我从 web 服务生成一个代理类,它只包含这样的异步调用。你提供的代码,loginAsync 是一个 void 方法,它不返回任何东西,所以我必须使用 loginCompleted 事件来获取结果.. 所以我必须使用 TaskCompletion
标签: c# async-await task deadlock