2012-01-05 17 views
9

コールバック引数を非同期に実行するメソッドがありますが、キャッチブロックは同期呼び出しによってスローされた例外をキャッチしていないようです(this.Submitは同期メソッドを指します) 。非同期コールバックでスローされた例外をキャッチ

public void Submit(FileInfo file, AnswerHandler callback) 
{ 
    SubmitFileDelegate submitDelegate = new SubmitFileDelegate(this.Submit); 
    submitDelegate.BeginInvoke(file, (IAsyncResult ar) => 
    { 
     string result = submitDelegate.EndInvoke(ar); 
     callback(result); 
    }, null); 
} 

新しいスレッドによってスローされた例外をキャッチし、元のスレッドに送信する方法はありますか?また、これは非同期例外を処理するための「適切な」方法ですか?

try 
{ 
    target.Submit(file, (response) => 
    { 
     // do stuff 
    }); 
} 
catch (Exception ex) 
{ 
    // catch stuff 
} 

をこれを行うには、より適切かエレガントな方法があります:それは(例外の問題は固定されていると仮定して)、このように呼ばれることができるよう、私は私のコードを書きましたの?

+0

最初のコードサンプルのcatchブロックは、コールバックまたはEndInvokeによってスローされた例外をキャッチします。2番目のコードサンプルのcatchブロックは、SubmitFileDelegateコンストラクターまたはBeginInvokeによってスローされた例外をキャッチします。あなたが期待していること/したいことをしていない人はどれですか? – dgvid

+0

おっと、削除するのを忘れました。私は第二のものが正しく働くことを望みますが、現時点ではどちらもありません。 – kevmo314

+0

'SubmitFileDelegate'の定義方法を教えてください。 – GolfWolf

答えて

8

これは「ベストプラクティス」ソリューションではありませんが、私はそれが動作するはず単純なものだと思う:TPLでの例外処理について

詳しい情報はここで見つけることができます。

代わり

private delegate string SubmitFileDelegate(FileInfo file); 

private delegate SubmitFileResult SubmitFileDelegate(FileInfo file); 

として定義し、次のようにSubmitFileResultを定義するように定義されたデリゲート有する:その後

public class SubmitFileResult 
{ 
    public string Result; 
    public Exception Exception; 
} 

、実際にないメソッドをファイル提出(質問には示されていません)は、次のように定義する必要があります:

private static SubmitFileResult Submit(FileInfo file) 
{ 
    try 
    { 
     var submissionResult = ComplexSubmitFileMethod(); 

     return new SubmitFileResult { Result = submissionResult }; 
    } 
    catch (Exception ex) 
    { 
     return new SubmitFileResult {Exception = ex, Result = "ERROR"}; 
    } 
} 

このようにして、結果オブジェクトを調べ、結果フィールドまたは例外フィールドが設定されているかどうかを確認し、それに従って処理します。

+0

この呼び出しは同期的ではありませんか?私はBeginInvokeコールバックにtry/catchを入れようとしましたが(あなたの例ではそうしていますが)、例外をキャッチしていないようです。 – kevmo314

+0

いいえ、同期していません。上に説明したもの( 'SubmitFileDelegate'の定義と一致するもの)とあなたが質問で提示したもの、' BeginInvoke'はもう一方のものです(これは非同期呼び出しであることを意味します) )。 – GolfWolf

3

要するに、

submitDelegate.BeginInvokeを呼び出すと、新しいスレッドが生成され、返され、すぐにtry/catchブロックが終了します(新しいスレッドはバックグラウンドで実行されます)。

ただし、このようすべて未処理の例外をキャッチできます。これは、アプリケーションドメインでしかし(だけでなく、あなたの非同期メソッドを)すべてをキャッチします

AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(YourException);

+0

例外を処理する方法がありますか?私はコールバックをJSワールドの関数(エラー、結果){}のようなものにするのに慣れていますが、C#のサンプルコードでは何も見たことがありません。それはC#で行われるはずです:S – kevmo314

+0

@ w0lfの答えは基本的にそれです;応答タイプ内で発生した例外をラップし、完了後に引き出します。 –

9

.NET 4.0を対象としている場合は、新しいタスク並列ライブラリを利用して、TaskオブジェクトのExceptionプロパティを観察できます。

public Task Submit(FileInfo file) 
{ 
    return Task.Factory.StartNew(() => DoSomething(file)); 
} 

private void DoSomething(FileInfo file) 
{ 
    throw new Exception(); 
} 

次に、このようにそれを使用する:DoSomethingはあなたが非同期的に呼び出して、あなたがContinueWithに渡すデリゲートがコールバックされたい方法です

Submit(myFileInfo).ContinueWith(task => 
{ 
    // Check task.Exception for any exceptions. 

    // Do stuff with task.Result 
}); 

http://msdn.microsoft.com/en-us/library/dd997415.aspx

関連する問題