14

WCF サービスを使用する Silverlight 2 アプリケーションがあります。そのため、サービスのメソッドへのすべての呼び出しに非同期コールバックを使用します。これらの呼び出しの前または実行中に、サービスが実行されていない場合、サービスがクラッシュした場合、またはネットワークがダウンした場合などは、期待どおりに例外が生成されます。問題は、この例外をキャッチする方法がわからないことです。

  • これは非同期呼び出しであるため、begin 呼び出しを try/catch ブロックでラップして、プログラムがその時点から移動した後に発生する例外を取得することはできません。

  • サービス プロキシは自動的に生成されるため、EndInvoke を呼び出すすべての生成済み関数 (例外が実際に表示される場所) に try/catch ブロックを配置することはできません。これらの生成された関数は、コール スタック内の外部コードにも囲まれているため、スタック内に try/catch を置く場所は他にありません。

  • コールバック関数が呼び出される前に例外が発生するため、try/catch をコールバック関数に入れることができません。

  • App.xaml.cs には Application_UnhandledException 関数があり、未処理の例外をすべてキャプチャします。これを使用できますが、面倒な方法のようです。この関数は、本当に予期しないエラー (別名バグ) 用に予約しておき、特定の方法で対処したいすべての状況でこの関数のコードを終わらせないようにしたいと思います。

明らかな解決策がありませんか?または、Application_UnhandledException を使用して立ち往生していますか?

[編集]
以下で説明するように、Error プロパティはまさに私が探していたものです。ループのために私をスローしているのは、例外がスローされ、キャッチされていないように見えるという事実ですが、実行は続行できます。Application_UnhandledException イベントをトリガーし、VS2008 で実行が中断されますが、デバッガーで続行すると実行を続行できます。それは実際には問題ではなく、奇妙に思えるだけです。

4

9 に答える 9

12

サービス メソッドの完了イベント ハンドラーで、イベント引数の Error プロパティを確認します。イベントハンドラーが呼び出されないという問題はありませんでした。サーバーがダウンした場合、呼び出しに数秒かかり、Error プロパティに ProtocolException が返されます。

これを試してもコールバックがまったく呼び出されないと仮定すると、生成されたプロキシ クラスのカスタマイズを検討することになるかもしれません。この記事を参照してください。

于 2008-09-18T17:49:32.070 に答える
5

これについて話しているフォーラム スレッドを見つけましたが、ベスト プラクティスは Error プロパティを使用することであると述べています。このスレッドと私自身の経験から、これは私が結論づけることができるものです:

  • 通常の .NET コードでは、生成されたプロキシ クラスは、例外をスローする代わりに Error プロパティに配置することで、例外を適切に処理します。

  • Silverlight では、生成されたプロキシ クラスは Error プロパティを設定しますが、例外を完全には処理しません。例外はデバッガーによって検出され、"ProtocolException was unhandled by user code" というメッセージが表示された例外ボックスが表示されます。このメッセージにもかかわらず、例外は実際には Application_UnhandledException 関数に到達していないようです。

これは、最終リリースで修正されるものの 1 つになると思います。

ここでは、Error プロパティを使用して、実行を中断するデバッガーのみに対処します。それが煩わしい場合は、ProtocolException のブレーク オン 例外をオフにすることができます。

于 2008-09-19T16:28:24.433 に答える
0

WP7のXNAでは、さまざまな非同期End * FunctionName *()メソッドにtry/catchを手動で追加する以外に選択肢がないことがわかりました。サーバーが利用できないときにアプリケーションの障害とシャットダウンを防ぐために私が試した他の方法はありません。サービスが変更されたときにこのコードを手動で更新しなければならないのは、本当に大変なことです。

XNAを使用してWP7でこれらの例外をキャッチする方法は他にないように思われるので、これが大きな問題ではないことに驚いていますが、これは、何人(==多くない)がやろうとしているのかを示しているだけだと思いますこれは何よりも。slsvcutil.exeに同期メソッドを生成させるだけであれば、独自のワーカースレッド内でこれらを簡単にキャッチできますが、残念ながら、生成されたコードは例外をキャッチする手段のないスレッドプールスレッドを使用します。

于 2011-06-03T07:30:47.590 に答える
0

asynクライアントコールバックのApplication_UnhandledExceptionを忘れることができます。理由は、次のとおりです。

Application_UnhandledExceptionは、UIスレッドで発生した例外のみをApplication.UnhandledExceptionsでキャッチできます。

これは...WCF非同期呼び出しではまったく呼び出されないことを意味します:-)。

MSFTからの詳細な応答を確認してください

http://silverlight.net/forums/t/21828.aspx

こんにちは、Application.UnhandledExceptionsでキャッチできるのはUIスレッドで発生した例外のみです。他のスレッドからの例外をキャッチすることはできません。これを試して、問題のトラブルシューティングを行うことができます。Visual Studioで、[デバッグ]メニューから[例外]を選択します。次に、「共通言語ランタイムの例外」を確認します。これにより、例外がスローされるたびにデバッガーが停止します。ただし、例外がすでにキャッチされている場合でも、これは非常に煩わしい場合があることに注意してください。チェックボックスを使用して、キャッチしたい例外をフィルタリングできます。

私の場合の朗報は、デバッグしていない場合は、clietnサービスのコールバックでエラーメッセージを処理するだけで十分です。

ありがとう

Braulio
于 2009-03-11T21:45:23.410 に答える
0

私は配管工ではないので、Visual Studioによって自動的に生成されるクラスファイル「reference.cs」の機能の一部をオーバーライドする独自のWCFサービスクラスを作成することにしました。次に、独自のtry/catchブロックをに追加しました。通信エラーをキャッチします。

私が作成したクラスは次のようになります。

public class myWCFService : MyWCFServiceClient
{

    protected override MyController.MyService.IMyWCFService CreateChannel()
    {
        return new MyWCFServiceClientChannel(this);
    }

}

private class MyWCFServiceClientChannel : ChannelBase<MyController.MyService.IMyWCFService>, MyController.MyService.IMyWCFService
{
    /// <summary>
    /// Channel Constructor
    /// </summary>
    /// <param name="client"></param>
    public MyWCFServiceClientChannel(System.ServiceModel.ClientBase<MyController.MyService.IMyWCFService> client) :
    base(client)
    {
    }
    /// <summary>
    /// Begin Call To RegisterUser
    /// </summary>
    /// <param name="memberInformation"></param>
    /// <param name="callback"></param>
    /// <param name="asyncState"></param>
    /// <returns></returns>
    public System.IAsyncResult BeginRegisterUser(MyDataEntities.MembershipInformation memberInformation, System.AsyncCallback callback, object asyncState)
    {               
        object[] _args = new object[1];
        _args[0] = memberInformation;
        System.IAsyncResult _result = base.BeginInvoke("RegisterUser", _args, callback, asyncState);
        return _result;               
    }
    /// <summary>
    /// Result from RegisterUser
    /// </summary>
    /// <param name="result"></param>
    /// <returns></returns>
    public MyDataEntities.MembershipInformation EndRegisterUser(System.IAsyncResult result)
    {
        try
        {
            object[] _args = new object[0];
            MyDataEntities.MembershipInformation _result = ((MyDataEntities.MembershipInformation)(base.EndInvoke("RegisterUser", _args, result)));
            return _result;
        }
         catch (Exception ex)
        {
            MyDataEntities.MembershipInformation _result = new MyDataEntities.MembershipInformation();
            _result.ValidationInformation.HasErrors = true;
            _result.ValidationInformation.Message = ex.Message;
            return _result;
        }
    }
}
于 2009-06-06T18:37:35.337 に答える
0

カスタム WCF プロキシ ジェネレーターを使用することは、Silver-light で非同期例外を処理するための優れたソリューションです。ソース コードをダウンロードするには、ここをクリックしてください。

于 2011-05-24T12:17:09.073 に答える
0

ああ……

私の側からの間違った回答で申し訳ありません(MSFTの担当者は、書き込み回答サービスのコールバックが同じUIスレッドで呼び出されていませんでした)、問題は

より詳しい情報:

- In development even detaching from the debugger, this method is never reached. 
- On the production environment yes.

私の推測では、Visual Studio のオプションと例外のインターセプトに関連するものです。

詳細については、このスレッドで http://silverlight.net/forums/p/48613/186745.aspx#186745

非常に興味深いトピックです。

于 2009-03-12T06:56:45.473 に答える
0

この状況を処理するには、TargetInvocationException を使用します。これにより、ネットワークがダウンしている場合やサービスが利用できない場合に例外がキャッチされます。

于 2012-08-24T05:49:49.037 に答える
0

Silverlight 3 では、Visual Studio デバッガーがこれらの例外をキャッチするため、紛らわしいことに、例外ハンドラーに到達することはありません。ただし、デバッガーなしで実行すると、例外ハンドラーは期待どおりに呼び出されます。これだけは意識しておけば大丈夫だと思います。Silverlight/Wcf/Browser の内部構造を掘り下げて例外に到達する方法を見つけようとして、数時間を無駄にしたことは認めます。そこに行かないでください。

于 2010-03-26T12:58:53.903 に答える