Unified Service Desk のカスタムのホストされたコントロールに SafeDispatcher を使用します

 

対象: Dynamics 365 (online)、Dynamics 365 (on-premises)、Dynamics CRM 2013、Dynamics CRM 2015、Dynamics CRM 2016

Unified Service Desk は、Unified Service Desk のすべての操作がメインの WPF ディスパッチャー スレッドで実行される Windows Presentation Foundation (WPF) ベースのアプリケーションです。WPF ディスパッチャー クラスは、スレッドの作業アイテムのキューを管理するためのサービスを提供します。

カスタム コントロールを作成し、Unified Service Desk 内でホストすることによって Unified Service Desk を拡張できます。 ただし、カスタムのホストされたコントロールが欠陥のあるコードを含んでいるか、コードの実行中に適切に例外を処理せずに新しいスレッドを使用する操作を実行すると、Unified Service Desk の安定性を脅かす問題が発生する可能性があり、クライアント アプリケーションがフリーズしたり応答しなくなる可能性があります。 サードパーティのカスタム コントロールで処理されない例外があると、製品 / サポート チームは Unified Service Desk でエラーや例外の発生理由またはエラーを発生した正確なコードの情報へのアクセス権がないため、問題を特定し、トラブルシューティングして解決するように試みます。

例外のソースおよび原因に関する詳細情報の標準ログ記録の提供およびその他の手順を実行するための SafeDispatcher 例外処理の構成または上書きによって Unified Service Desk のカスタムのホストされたコントロールに強力かつ有益な例外処理機能を提供する SafeDispatcher の導入。 これは、Unified Service Desk クライアントがカスタムのホストされたコントロール コードの処理されない例外のため、応答しなくなることを防ぎます。

注意

この機能は Unified Service Desk 2.2.1 に導入されています。

このトピックの内容

SafeDispatcher とは

SafeDispatcher の使用方法

既存のカスタムのホストされたコントロールでの WPF ディスパッチャーから SafeDispatcher への移行

SafeDispatcher を使用するときに考慮する事項

SafeDispatcher とは

SafeDispatcher は、WPF ディスパッチャー と同じ行に構築され、Unified Service Desk 内のカスタムのホストされたコントロールに弾性のある有益な例外処理を提供します。 これは保護されたプロパティ SafeDispatcher として DynamicsBaseHostedControl クラスで公開され、SafeDispatcher を DynamicsBaseHostedControl クラスから派生するすべての Unified Service Desk のカスタムのホストされたコントロールに対して自動的に利用できます。

注意

コード内で SafeDispatcher クラスを SafeDispatcher に関する作業に使用しないでください。 代わりに、SafeDispatcher を使用するために DynamicsBaseHostedControl クラスから派生するカスタムのホストされたコントロールのインスタンスで SafeDispatcher プロパティを使用する必要があります。

WPF ディスパッチャー と同様に、SafeDispatcher は、UI スレッドで SafeDispatcher を実行するかどうかを制御する追加のブール値のパラメーター runOnMainUiThread を持つ SafeDispatcher で同期的または非同期的に操作を実行するための BeginInvokeInvokeInvokeAsync などのメソッドを提供します。

SafeDispatcher には次のような利点があります。

  • 保護された UI ディスパッチャーのスレッド: 開発者は、UI スレッドで SafeDispatcher を実行する呼び出しメソッドで runOnMainUiThread パラメーターを "true" に設定することで、SafeDispatcher のすべての UI 依存操作を実行できます。 メインの UI ディスパッチャーで発生するあらゆる処理されない例外は、グローバル DispatcherUnhandledException イベント ハンドラーを増加せずに、ホストされたコントロール レベルで安全に処理されます。

  • 保護された 非 UI ディスパッチャー スレッド: 開発者は SafeDispatcher ですべての UI 非依存コードを実行できます。 非 UI スレッドの SafeDispatcher を実行する呼び出しメソッドで runOnMainUiThread パラメーターを "false" に設定します。 メインの 非 UI ディスパッチャーで発生するあらゆる処理されない例外は、グローバル DispatcherUnhandledException イベント ハンドラーを増加せずに、ホストされたコントロール レベルで安全に処理されます。

  • 例外のソースおよび原因に関する詳細情報:: SafeDispatcher 例外ハンドラーは、処理されない例外が UI スレッドまたは非 UI スレッドによって DynamicsBaseHostedControl レベルで発生するときに発生し、Unified Service Desk がホストされたコントロール名、ホストされたコントロールの種類、メソッド名などのホストされたコントロール レベルでの重要な情報を取得して、例外の正確な場所と原因を特定できるようにします。

  • SafeDispatcher 例外ハンドラーの構成または上書き: 開発者は、処理されない例外に関する情報についてユーザーを要求する SafeDispatcher 例外ハンドラーの標準の動作を活用したり、追加のログ記録の構成、セッション ベースのコントロールのクローズ、または Unified Service Desk クライアントの終了などの業務要件を上書きしたりできます。

SafeDispatcher の使用方法

SafeDispatcher プロパティは、DynamicsBaseHostedControl クラスから派生する Unified Service Desk のカスタムのホストされたコントロールのインスタンスすべてに使用できます。SafeDispatcherインスタンスは、カスタムのホストされたコントロールが初期化されると UI スレッドで実行して使用できます。 ただし、SafeDispatcher インスタンスは呼び出しメソッドを初めて実行するとき、非 UI スレッドでの実行にのみ利用できます。

  • 同期的に SafeDispatcher を使用する UI 固有の機能を呼び出します

    SafeDispatcher.Invoke(() =>
                {
                    ProcessData();
                }, DispatcherPriority.Normal, CancellationToken.None, true);
    

    または

    SafeDispatcher.Invoke(() =>
                {
                    ProcessData();
                }, DispatcherPriority.Normal, CancellationToken.None);
    

    注意

    UI 固有の機能では、runOnMainUiThread のオプション パラメーターを「true」に設定する必要があります。 このパラメーターの値を指定しない場合、既定で「true」が渡されます。 したがって、上記のメソッドの定義はいずれもうまく機能します。

  • 非同期的に SafeDispatcher を使用する UI 固有の機能を呼び出します。BeginInvoke または InvokeAsync メソッドを使用できます。

    SafeDispatcher.BeginInvoke(new Action(() =>
                {
                   ProcessData();
                }));
    

    または

    SafeDispatcher.InvokeAsync(new Action(() =>
                {
                   ProcessData();
                }));
    

SafeDispatcher 例外ハンドラーをカスタマイズします

SafeDispatcher の導入で、Unified Service Desk のすべての処理されない例外は、グローバル DispatcherUnhandledException イベント の代わりに SafeDispatcherUnhandledException Event を発生させます。SafeDispatcherUnhandledExceptionHandler Method は、次の詳細を Unified Service Desk ユーザーに表示するために SafeDispatcher に標準の例外ハンドラーを提供します。

セッション ベースの非動的なホストされたコントロールを閉じるユーザーへのプロンプトなどその他の操作を実行するために、SafeDispatcher の標準の例外処理を上書きすることもできます。

次のサンプル コードは、例外の発生時にカスタムのホストされたコントロールを閉じるプロンプトを表示するために標準の SafeDispatcher 例外ハンドラーを上書きできる方法を示します。

protected override void SafeDispatcherUnhandledExceptionHandler(object sender, SafeDispatcherUnhandledExceptionEventArgs ex)
{
    string error = String.Format(CultureInfo.InvariantCulture,
        "Error in hosted control  Application:{0} - Exception : {1} \r\nInnerException\r\n {2}", this.ApplicationName, ex.Exception, ex.InnerException);
    DynamicsLogger.Logger.Log(error, TraceEventType.Error);
    if (MessageBox.Show("Exception occurred in hosted control - " + this.ApplicationName + ".Do you wish to close it ?", "Question", MessageBoxButton.YesNo,
        MessageBoxImage.Warning) == MessageBoxResult.Yes)
    {
        SafeDispatcher.BeginInvoke(() => { this.desktopAccess.CloseDynamicApplication(this.ApplicationName); });
    }
}

既存のカスタムのホストされたコントロールでの WPF ディスパッチャーから SafeDispatcher への移行

WPF ディスパッチャーと SafeDispatcher の間の契約はほとんど同じなので、WPF ディスパッチャーから SafeDispatcher への移行のための作業は最小限です。DynamicsBaseHostedControl クラスから派生するホストされたコントロールを移行するには、「SafeDispatcher」で「Dispatcher」のすべてのインスタンスを置き換えます。

たとえば、次のようなコードが考えられます。

Dispatcher.Invoke((System.Action)delegate()
{
    DynamicsLogger.Logger.Log("Raising SetupHotKey's", TraceEventType.Verbose);
    SetupHotkeys();
    CRMGlobalManager.AppWithFocusChanged += CRMGlobalManager_AppWithFocusChanged;
    FireEvent("DesktopReady");
    InitializeFocusSelection();
});

上記のコードの DispatcherSafeDispatcher に置き換え、残りのコードはそのままにします。

SafeDispatcher.Invoke((System.Action)delegate()
{
    DynamicsLogger.Logger.Log("Raising SetupHotKey's", TraceEventType.Verbose);
    SetupHotkeys();
    CRMGlobalManager.AppWithFocusChanged += CRMGlobalManager_AppWithFocusChanged;
    FireEvent("DesktopReady");
    InitializeFocusSelection();
});

SafeDispatcher を使用するときに考慮する事項

SafeDispatcher は、UI または非 UI スレッドに関数を同期的または非同期的にディスパッチするのに非常に有利なマルチスレッド モデルを提供します。 フォールト トレランスとともに利用できるスレッドで実行する必要がある操作は、SafeDispatcher で実行する必要があります。 ただし、マルチスレッドはスレッド間のデッドロックを回避するために、非常に注意深く実装する必要があります。 こうした例の 1 つは、非 UI スレッドからメインの WPF ディスパッチャーに同期的にディスパッチすることです。 この例を検討します。

Thread thread = new Thread(() =>
{
    Dispatcher.Invoke(ProcessData);
});
thread.SetApartmentState(ApartmentState.STA);
thread.Priority = ThreadPriority.Highest;
thread.IsBackground = true;
thread.Start();
thread.Join();

thread.Join() メソッドは、シングルスレッド アパートメント (STA) の終了するまでメイン スレッドをブロックして待機しますが、STA スレッドはメイン スレッドが ProcessData の実行を終了するまで待機します。 これにより、アプリケーションのデッドロック状況が発生します。

同様に、次のような例が考えられます。

// Invoke on STA thread
SafeDispatcher.Invoke(() =>
{
    // Invoke back on main dispatcher
    SafeDispatcher.Invoke(() =>
    {
        ProcessData();
    });
}, false);

例外が WPF ディスパッチャーまたは STA 非 UI スレッドで発生し、発生したそれぞれのスレッドで発生する場合、SafeDispatcherUnhandledExceptionHandler Method が呼び出されます。 非 UI スレッドが発生した場合に、このハンドラーで上記の組み合わせを配置しておらず、同期的にメイン UI のディスパッチャーにディスパッチしないように注意する必要があります。

protected override void SafeDispatcherUnhandledExceptionHandler(object sender, SafeDispatcherUnhandledExceptionEventArgs ex)
{
    Dispatcher.Invoke(LogException);                    // Incorrect
    SafeDispatcher.Invoke(LogException);            // Incorrect
    SafeDispatcher.BeginInvoke(LogException);  // Correct
    SafeDispatcher.InvokeAsync(LogException); // Correct
}

関連項目

チュートリアル: Unified Service Desk のカスタムのホストされたコントロールの作成
統合サービス デスクの拡張
TechNet: Unified Service Desk でのクライアント診断ログの構成

Unified Service Desk 2.0

© 2017 Microsoft. All rights reserved. 著作権