我很新于新的异步/等待功能。然而,我有以下类:
public abstract class PluginBase
{
//Using EF to store log info to database
private EFContext _context = new EFContext();
private int Id = 1;
protected void LogEvent(string event, string details)
{
_context.LogEvents.Add(new LogItem(){
PluginId = this.Id,
Event = event,
Details = details,
User = Thread.CurrentPrincipal.Identity.Name
});
}
}
public class Plugin : PluginBase
{
public void Process()
{
CallWebService();
}
public async void CallWebService()
{
using(var http = new HttpClient())
{
...
var result = await http.PostAsync(memberURI, new StringContent(content, Encoding.UTF8,"application/json"));
if(result.IsSuccessStatusCode)
_status = "Success";
else
_status = "Fail";
LogEvent("Service Call - " + _status,...);
}
}
所以,这个想法是调用Plugin.Process。它又调用CallWebService()。CallWebService发起异步调用http.PostAsync。当我从该调用返回并尝试调用base.LogEvent()时,我会收到一个ObjectDisposedException,指出"Safe Handle has been Closed"。
我知道在等待完成后,该方法的其余代码必须运行。也许它正在某个其他线程或上下文中运行?如果是这种情况,我如何在写入日志时获取当前用户?
感谢您对此的帮助。
编辑 根据Yuval的答案,我做了以下更改,似乎工作正常。
public void Process()
{
var task = CallWebService();
task.Wait();
}
public async Task CallWebService(List<Member> members)
{
using(var http = new HttpClient())
{
...
using(var result = await http.PostAsync(memberURI, new StringContent content, Encoding.UTF8, "application/json")))
{
if(result.IsSuccessStatusCode)
_status = "Success";
else
_status = "Fail";
LogEvent("Service Call - " + _status,...);
}
}
}
task.Wait()
。正确的解决方案是让Processspublic Task Process()
并使其返回或等待从CallWebService返回的任务。如果你调用Wait()
会很容易导致死锁。如果你想使用await
,你必须一直使用它到调用链的最上层。如果不能更改Process来返回任务,则不要使用PostAsync
而是使用Post
,并且不使用async/await。 - Scott Chamberlain