Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 尝试使用异步方法访问Thread.CurrentPrincipal时发生ObjectDisposedException_C#_Multithreading_Asynchronous_Async Await - Fatal编程技术网

C# 尝试使用异步方法访问Thread.CurrentPrincipal时发生ObjectDisposedException

C# 尝试使用异步方法访问Thread.CurrentPrincipal时发生ObjectDisposedException,c#,multithreading,asynchronous,async-await,C#,Multithreading,Asynchronous,Async Await,我对新的async/await内容还相当陌生。但是,我有以下课程: 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) {

我对新的async/await内容还相当陌生。但是,我有以下课程:

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,...);
        }
    }
 }
公共作废流程()
{
var task=CallWebService();
task.Wait();
}
公共异步任务CallWebService(列表成员)
{
使用(var http=new HttpClient())
{
...
使用(var result=await http.PostAsync(memberURI,newstringcontent,Encoding.UTF8,“application/json”))
{
if(结果。IsSuccessStatusCode)
_status=“Success”;
其他的
_status=“Fail”;
LogEvent(“服务调用-”+_状态,…);
}
}
}
当我从那个调用返回并尝试调用base.LogEvent()时,我得到一个 ObjectDisposedException声明“安全句柄已关闭”

这是因为在调用链的更高层,有人正在处理你的插件对象,而这个对象还没有真正完成异步操作。使用
async void
是执行“触发并忘记”操作。实际上,您并没有在
进程上等待
,因此任何调用它的人都会假定它已完成并处理您的对象

async void
方法更改为
async Task
,然后
等待它:

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,...);
   }
}

注意,您还需要在调用堆栈的更高位置等待ProcessAsync。

您能解释一下吗?我看不到在您的CallWebServiceAsync代码中返回任务。等待是否导致任务返回?进程是否可以等待该任务,而不是将其进一步传递到管道上?我没有看到在CallWebServiceAsync中返回任务。该任务是由编译器生成的状态机隐式创建的。您可以在
CallWebService
Wait
,但如果已在等待
ProcessAsync
,则这将是多余的。使用async时,不要在代码中执行
task.Wait()
。正确的解决方案是使Processs
public Task Process()
,并让它返回或等待从CallWebService返回的任务。如果调用
Wait()
很有可能导致死锁。如果您想使用
wait
,则必须在呼叫链的整个过程中使用它。如果无法将进程更改为返回任务,则不要使用
PostAsync
,只需使用
Post
,而不要使用async/await。