簡體   English   中英

嘗試使用異步方法訪問Thread.CurrentPrincipal時出現ObjectDisposedException

[英]ObjectDisposedException when trying to access Thread.CurrentPrincipal with async method

我對新的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,指出“Safe Handle已被關閉”。

我知道當等待完成時會發生一些事情,必須運行該方法的其余代碼。 也許它在其他一些線程或上下文中運行? 如果是這種情況,如何在寫入日志時獲取當前用戶?

感謝您對此的幫助。

編輯根據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,...);
        }
    }
 }

當我從該調用返回並嘗試調用base.LogEvent()時,我得到一個ObjectDisposedException,指出“Safe Handle已被關閉”。

那是因為在調用鏈的某個地方,有人正在處理你的插件對象,而這個對象還沒有真正完成異步操作。 使用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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM