尝试使用异步方法访问Thread.CurrentPrincipal时出现ObjectDisposedException

时间:2015-06-01 15:34:18

标签: 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)
   {
       _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,...);
        }
    }
 }

1 个答案:

答案 0 :(得分:3)

  

当我从该调用返回并尝试调用base.LogEvent()时,我得到了一个   ObjectDisposedException指出&#34;安全句柄已关闭&#34;。

那是因为在调用链的某个地方,有人正在处理你的插件对象,它还没有真正完成异步操作。使用async void正在进行“火灾”并忘记&#34;操作。你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

请注意,您还需要 I have tried executing storm hdfs sample program. I have created a jar file and copied the jar to the edge node of the cluster. Then I executed the below command java -cp storm-.1.jar:lib/*:lib/log4j.properties test.storm.sample.StormSampleTopology But, I am getting the below exception 17434 [Thread-11-hdfs_bolt] WARN org.apache.hadoop.ipc.Client - Exception encountered while connecting to the server : java.lang.IllegalArgumentException: Failed to specify server's Kerberos principal name 17448 [Thread-9-hdfs_bolt] WARN org.apache.hadoop.ipc.Client - Exception encountered while connecting to the server : java.lang.IllegalArgumentException: Failed to specify server's Kerberos principal name 17457 [Thread-11-hdfs_bolt] ERROR backtype.storm.util - Async loop died! java.lang.RuntimeException: Error preparing HdfsBolt: Failed on local exception: java.io.IOException: java.lang.IllegalArgumentException: Failed to specify server's Kerberos principal name; Host Details : local host is: "xxxx2002.xx.xxxxx.com/11.11.111.221"; destination host is: "x-xxxxx.xxxx.com":8020; at org.apache.storm.hdfs.bolt.AbstractHdfsBolt.prepare(AbstractHdfsBolt.java:96) ~[storm-hdfs-0.1.2.jar:na] at backtype.storm.daemon.executor$fn__3441$fn__3453.invoke(executor.clj:692) ~[storm-core-0.9.3.jar:0.9.3] at backtype.storm.util$async_loop$fn__464.invoke(util.clj:461) ~[storm-core-0.9.3.jar:0.9.3] at clojure.lang.AFn.run(AFn.java:24) [clojure-1.5.1.jar:na] at java.lang.Thread.run(Thread.java:744) [na:1.7.0_45] Caused by: java.io.IOException: Failed on local exception: java.io.IOException: java.lang.IllegalArgumentException: Failed to specify server's Kerberos principal name; Host Details : local host is: "xxx2002.xx.xxx.com/11.11.111.221"; destination host is: "x-xxxx.xxx.com":8020; at org.apache.hadoop.net.NetUtils.wrapException(NetUtils.java:772) ~[hadoop-common-2.6.0.2.2.0.0-2041.jar:na] at org.apache.hadoop.ipc.Client.call(Client.java:1472) ~[hadoop-common-2.6.0.2.2.0.0-2041.jar:na] at org.apache.hadoop.ipc.Client.call(Client.java:1399) ~[hadoop-common-2.6.0.2.2.0.0-2041.jar:na] at org.apache.hadoop.ipc.ProtobufRpcEngine$Invoker.invoke(ProtobufRpcEngine.java:232) ~[hadoop-common-2.6.0.2.2.0.0-2041.jar:na] at com.sun.proxy.$Proxy14.create(Unknown Source) ~[na:na] at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolTranslatorPB.create(ClientNamenodeProtocolTranslatorPB.java:295) ~[hadoop-hdfs-2.6.0.2.2.0.0-2041.jar:na] 更高的调用堆栈。