12

Async CTP を使用して IO 負荷の高いコンソール アプリを作成しています。しかし、私は例外に問題があります。

public static void Main()
{
   while (true) {
     try{
         myobj.DoSomething(null);
     }
     catch(Exception){}
     Console.Write("done");
     //...
   }
}

//...
public async void DoSomething(string p)
{
   if (p==null) throw new InvalidOperationException();
   else await SomeAsyncMethod();
}

そして、次のことが起こります:「完了」がコンソールに書き込まれ、デバッガーで例外が発生し、続行を押しますmy program exists .
何を与える?

4

2 に答える 2

29

コンソール アプリケーションに非同期互換のコンテキスト (たとえば、私の AsyncEx ライブラリのAsyncContext( docs , sourceasync void )) を与えると、メソッドからであっても、そのコンテキストから伝播する例外をキャッチできます。

public static void Main()
{
  try
  {
    AsyncContext.Run(() => myobj.DoSomething(null));
  }
  catch (Exception ex)
  {
    Console.Error.WriteLine(ex.Message);
  }
  Console.Write("done");
}

public async void DoSomething(string p)
{
  if (p==null) throw new InvalidOperationException();
  else await SomeAsyncMethod();
}
于 2011-09-08T15:25:08.437 に答える
15

あなたがそれを呼び出すDoSomething()と、基本的Taskにボンネットの下に を作成し、それを開始しTaskます。void署名があったためTask、信号を返すオブジェクトやブロックできた可能性のあるオブジェクトがないため、実行はすぐに終了しました。その間、タスクは例外をスローしますが、誰もキャッチしていません。これが、プログラムが終了する理由だと思います。

あなたが望んでいた動作は次のようなものだと思います:

public static void Main()
{
   while (true) {
     var t = myobj.DoSomething(null);
     t.Wait();
     if(t.HasException) {
       break;
     }
   }
   Console.Write("done");
   //...
  }
}

//...
public async Task DoSomething(string p)
{
  if (p==null) throw new InvalidOperationException();
  else await SomeAsyncMethod();
}

DoSomethingこれは、完了するまでそれぞれをブロックし、スローされた場合はループを終了しますDoSomething。もちろん、実際には何も非同期に行っているわけではありません。しかし、疑似コードからは、非同期で何をしたいのかよくわかりません。

主なポイント:void非同期メソッドに使用すると、その非同期メソッドを実行しない限り、例外を取得できなくなりますawait。同期呼び出しとして、基本的には作業をスケジュールするだけで、結果はエーテルに消えます。

于 2011-06-08T20:00:14.853 に答える