다음을 통해 공유


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에서 발생한 오류/예외가 발생한 이유에 대한 정보와 오류를 발생시킨 정확한 코드에 액세스할 수 없기 때문에 제품/지원 팀에서 식별, 문제 해결 및 문제 해결이 어렵습니다.

원본과 예외의 원인에 대한 자세한 정보와 함께 처리되지 않은 예외에 대한 기본 제공 로깅을 제공하여 Unified Service Desk에 사용자 지정 호스팅된 컨트롤에 대한 강력하고 유용한 예외 처리 메커니즘을 제공하는 SafeDispatcher로 몇 가지 다른 단계를 수행하는 SafeDispatcher 예외 처리를 구성하거나 덮어쓸 수 있습니다. 이는 또한 사용자 지정 호스팅된 컨트롤 코드의 예외가 처리되지 않아 Unified Service Desk 클라이언트가 응답하지 않는 것을 방지합니다.

참고

이 기능은 Unified Service Desk 2.2.1에 소개되었습니다.

이 항목의 내용

SafeDispatcher는 무엇입니까?

SafeDispatcher를 사용하는 방법

기존 사용자 지정 호스팅된 컨트롤에서 WPF 디스패처로부터 SafeDispatcher로 마이그레이션

SafeDispatcher를 사용할 때 고려해야 할 사항

SafeDispatcher는 무엇입니까?

SafeDispatcherWPF 디스패처와 같은 라인에서 빌드되며 Unified Service Desk 내의 사용자 지정 호스팅된 컨트롤에 대한 탄력적이고 유용한 예외 처리를 제공합니다.DynamicsBaseHostedControl 클래스에서 파생된 SafeDispatcher를 자동으로 모든 Unified Service Desk 사용자 지정 호스팅된 컨트롤에 사용 가능하게 만드는 DynamicsBaseHostedControl 클래스에 보호되는 속성(SafeDispatcher)으로 노출됩니다.

참고

SafeDispatcher에서 작동하게 하려면 코드에서 SafeDispatcher 클래스를 사용하지 마십시오. 대신 SafeDispatcher를 사용하기 위해 DynamicsBaseHostedControl 클래스에서 파생된 사용자 지정 호스팅된 컨트롤 인스턴스의 SafeDispatcher 속성을 사용해야 합니다.

WPF 디스패처와 같이 SafeDispatcher는 BeginInvoke, InvokeInvokeAsync 같은 메서드를 제공하여 SafeDispatcher에서 UI 스레드의 SafeDispatcher를 실행할지 여부를 제어하는 추가적인 부울 매개변수인 runOnMainUiThread와 동기적으로 또는 비동기적으로 작업을 실행할 수 있습니다.

SafeDispatcher는 다음과 같은 혜택을 제공합니다.

  • 보호되는 UI 디스패처 스레드: 개발자는 UI 스레드에서 SafeDispatcher를 실행하기 위해 호출 메서드에서 runOnMainUiThread 매개 변수를 "true"로 설정하여 SafeDispatcher에서 모든 UI 기반 작업을 실행할 수 있습니다. 기본 UI 디스패처에서 발생한 처리되지 않은 예외는 전역 DispatcherUnhandledException 이벤트 처리기로 버블링되는 대신 호스팅된 컨트롤 수준에서 안전하게 처리됩니다.

  • 보호된 비 UI 디스패처 스레드: 개발자가 SafeDispatcher에서 모든 UI 독립 코드를 실행할 수 있습니다. 호출 메서드에서 runOnMainUiThread 매개 변수를 "false"로 설정하여 비 UI 스레드에서 SafeDispatcher를 실행할 수 있습니다. 메인 비-UI 디스패처에서 발생한 처리되지 않은 예외는 전역 DispatcherUnhandledException 이벤트 처리기로 버블링되는 대신 호스팅된 컨트롤 수준에서 안전하게 처리됩니다.

  • 예외 원본과 원인에 대한 자세한 정보: UI 또는 비 UI 스레드에 의해 DynamicsBaseHostedControl 수준에서 처리되지 않은 예외가 발생할 때 SafeDispatcher 예외 처리기가 발생하며 이로 인해 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는 SafeDispatcher에 대한 기본 제공 예외 처리기를 제공하여 Unified Service Desk 사용자에게 예외가 발생한 원본 컨트롤 및 예외에 대한 자세한 정보를 표시합니다.

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 클래스에서 파생된 호스팅된 컨트롤 인스턴스를 마이그레이션하려면 모든 "Dispatcher" 인스턴스를 "SafeDispatcher"로 바꿉니다.

예를 들어 다음 코드를 고려합니다.

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에서 실행되어야 합니다. 그러나 다중 스레딩은 스레드 간 교착 상태를 방지하기 위해 매우 신중하게 구현해야 합니다. 일단 한 가지 예로는 동기적으로 비 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(single-threaded apartment)의 종료를 기다리는 메인 스레드를 차단되게 하나 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에 대한 사용자 지정 호스팅된 컨트롤 만들기
Unified Service Desk 확장
TechNet: Unified Service Desk에서 클라이언트 진단 로깅 구성

Unified Service Desk 2.0

© 2017 Microsoft. All rights reserved. 저작권 정보