我对新的异步/等待的东西还很陌生。但是,我有以下类(class):

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,指出“安全句柄已关闭”。

我知道在等待完成时,该方法的其余代码必须在哪里运行。也许它在其他线程或上下文中运行?在这种情况下,如何在写入日志时获取当前用户?

感谢您的帮助。

编辑
根据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,...);
        }
    }
 }

最佳答案



那是因为在调用链的更高处,有人正在处理您的插件对象,但实际上并没有完成异步操作。使用async void正在执行“即发即弃”操作。您实际上并没有在await上使用Process,因此任何调用它的人都假定它完成了并处理了您的对象。

将您的async void方法更改为async Task,并对其进行await:

public Task ProcessAsync()
{
    return CallWebServiceAsync();
}

public async Task CallWebServiceAsync()
{
   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,...);
   }
}

请注意,您还需要在调用堆栈的更高位置处await ProcessAsync

关于c# - 尝试使用异步方法访问Thread.CurrentPrincipal时出现ObjectDisposedException,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30577518/

10-13 23:54