다음을 통해 공유


이벤트 기반 비동기 패턴 구현

눈에 띄는 지연이 발생할 수 있는 일부 작업을 사용하여 클래스를 작성하는 경우 이벤트 기반 비동기 패턴을 구현하여 비동기 기능을 제공하는 것이 좋습니다.

이벤트 기반 비동기 패턴은 비동기 기능이 있는 클래스를 패키지하는 표준화된 방법을 제공합니다. 같은 AsyncOperationManager도우미 클래스를 사용하여 구현되는 경우 클래스는 ASP.NET, 콘솔 애플리케이션 및 Windows Forms 애플리케이션을 비롯한 모든 애플리케이션 모델에서 올바르게 작동합니다.

이벤트 기반 비동기 패턴을 구현하는 예제는 방법: 이벤트 기반 비동기 패턴을 지원하는 구성 요소 구현을 참조하세요.

간단한 비동기 작업의 경우 구성 요소가 적합할 BackgroundWorker 수 있습니다. 자세한 BackgroundWorker내용은 방법: 백그라운드에서 작업 실행을 참조하세요.

다음 목록에서는 이 항목에서 설명하는 이벤트 기반 비동기 패턴의 기능을 설명합니다.

  • 이벤트 기반 비동기 패턴을 구현할 수 있는 기회

  • 비동기 메서드 이름 지정

  • 선택적으로 취소 지원

  • 선택적으로 IsBusy 속성 지원

  • 필요에 따라 진행률 보고에 대한 지원 제공

  • 필요에 따라 증분 결과 반환 지원 제공

  • 메서드에서 Out 및 Ref 매개 변수 처리

이벤트 기반 비동기 패턴을 구현할 수 있는 기회

다음과 같은 경우 이벤트 기반 비동기 패턴을 구현하는 것이 좋습니다.

  • 클래스의 클라이언트는 WaitHandleIAsyncResult 개체가 비동기 작업에 사용 가능할 필요가 없으며, 이는 폴링 및 WaitAll 또는 WaitAny를 클라이언트가 구성해야 함을 의미합니다.

  • 친숙한 이벤트/대리자 모델을 사용하여 클라이언트에서 비동기 작업을 관리하려고 합니다.

모든 작업은 비동기 구현의 후보이지만 긴 대기 시간이 발생할 것으로 예상되는 작업을 고려해야 합니다. 특히 클라이언트가 메서드를 호출하고 완료 시 추가 개입 없이 알림을 수신하는 작업이 적합합니다. 또한 진행률, 증분 결과 또는 상태 변경 내용을 클라이언트에 주기적으로 알리며 지속적으로 실행되는 작업도 적합합니다.

이벤트 기반 비동기 패턴을 지원할 시기를 결정하는 방법에 대한 자세한 내용은 이벤트 기반 비동기 패턴을 구현할 시기 결정을 참조하세요.

비동기 메서드 이름 지정

비동기 대응을 제공하려는 각 동기 메서드 MethodName 에 대해 다음을 수행합니다.

다음을 수행할 MethodNameAsync 메서드를 정의합니다.

  • void을(를) 반환합니다.

  • MethodName 메서드와 동일한 매개 변수를 사용합니다.

  • 여러 호출을 허용합니다.

선택적으로 MethodNameAsync 오버로드를 정의합니다. 이 오버로드는 MethodNameAsync와 동일하지만 추가 개체 반환 매개 변수는 호출됩니다 userState. 메서드의 여러 동시 호출을 관리할 준비가 된 경우 이 작업을 수행합니다. 이 경우 userState 값은 메서드 호출을 구분하기 위해 모든 이벤트 처리기에 다시 전달됩니다. 나중에 검색할 수 있도록 사용자 상태를 저장하는 위치로 이 작업을 간단하게 수행할 수도 있습니다.

각 개별 MethodNameAsync 메서드 서명에 대해 다음을 수행합니다.

  1. 메서드와 동일한 클래스에서 다음 이벤트를 정의합니다.

    Public Event MethodNameCompleted As MethodNameCompletedEventHandler
    
    public event MethodNameCompletedEventHandler MethodNameCompleted;
    
  2. 다음 대리자를 정의하고 AsyncCompletedEventArgs. 클래스 자체 외부에서 정의될 수 있지만 동일한 네임스페이스에 정의될 수 있습니다.

    Public Delegate Sub MethodNameCompletedEventHandler( _
        ByVal sender As Object, _
        ByVal e As MethodNameCompletedEventArgs)
    
    Public Class MethodNameCompletedEventArgs
        Inherits System.ComponentModel.AsyncCompletedEventArgs
    Public ReadOnly Property Result() As MyReturnType
    End Property
    
    public delegate void MethodNameCompletedEventHandler(object sender,
        MethodNameCompletedEventArgs e);
    
    public class MethodNameCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
    {
        public MyReturnType Result { get; }
    }
    
    • 필드가 데이터 바인딩을 방지하므로 MethodNameCompletedEventArgs 클래스가 해당 멤버를 필드가 아닌 읽기 전용 속성으로 노출하는지 확인합니다.

    • 결과를 생성하지 않는 메서드에 대해 파생 클래스를 정의 AsyncCompletedEventArgs하지 마세요. 자체 인스턴스 AsyncCompletedEventArgs 를 사용하기만 하면 됩니다.

      비고

      가능하고 적절한 경우 대리자와 AsyncCompletedEventArgs 형식을 다시 사용하는 것이 완벽하게 허용됩니다. 이 경우, 지정된 델리게이트와 AsyncCompletedEventArgs는 단일 메서드에 연결되지 않기 때문에 명명은 메서드 이름과 일관되지 않을 것입니다.

선택적으로 취소 지원

클래스가 비동기 작업 취소를 지원하는 경우 아래 설명된 대로 취소가 클라이언트에 노출되어야 합니다. 취소 지원을 정의하기 전에 도달해야 하는 두 가지 의사 결정 지점이 있습니다.

  • 당신의 클래스는, 향후 예상되는 추가 사항을 포함하여 취소를 지원하는 비동기 작업이 하나만 있습니까?
  • 취소를 지원하는 비동기 작업이 여러 보류 중인 작업을 지원할 수 있나요? 즉, MethodNameAsync 메서드는 매개 변수를 userState 사용하며 완료될 때까지 기다리기 전에 여러 호출을 허용합니까?

아래 표에서 이러한 두 질문에 대한 답변을 사용하여 취소 방법에 대한 서명을 결정합니다.

Visual Basic (비주얼 베이직 언어)

여러 동시 작업 지원 한 번에 하나의 작업만
전체 클래스에서 하나의 비동기 작업 Sub MethodNameAsyncCancel(ByVal userState As Object) Sub MethodNameAsyncCancel()
클래스의 여러 비동기 작업 Sub CancelAsync(ByVal userState As Object) Sub CancelAsync()

C# (프로그래밍 언어)

여러 동시 작업 지원 한 번에 하나의 작업만
전체 클래스에서 하나의 비동기 작업 void MethodNameAsyncCancel(object userState); void MethodNameAsyncCancel();
클래스의 여러 비동기 작업 void CancelAsync(object userState); void CancelAsync();

메서드를 CancelAsync(object userState) 정의하는 경우 클라이언트는 단일 비동기 메서드의 모든 호출이 아니라 개체에서 호출된 모든 비동기 메서드를 구분할 수 있도록 상태 값을 선택할 때 주의해야 합니다.

단일 비동기 작업 버전 인 MethodNameAsyncCancel 의 이름을 지정하는 결정은 Visual Studio의 IntelliSense와 같은 디자인 환경에서 메서드를 보다 쉽게 검색할 수 있는 방법을 기반으로 합니다. 관련 멤버를 그룹화하고 비동기 기능과 아무런 관련이 없는 다른 멤버와 구분합니다. 후속 버전에서 비동기 작업이 추가될 것으로 예상하는 경우, CancelAsync을 정의하는 것이 좋습니다.

위의 테이블에서 동일한 클래스의 여러 메서드를 정의하지 마세요. 이는 의미가 없거나 메서드의 확산으로 클래스 인터페이스를 어지럽히는 것입니다.

이러한 메서드는 일반적으로 즉시 반환되며 작업이 실제로 취소되거나 취소되지 않을 수 있습니다. MethodNameCompleted 이벤트에 대한 이벤트 처리기에서 MethodNameCompletedEventArgs 개체에는 클라이언트가 취소가 발생했는지 여부를 확인하는 데 사용할 수 있는 필드가 포함 Cancelled 됩니다.

이벤트 기반 비동기 패턴을 구현하기 위한 모범 사례에 설명된 취소 의미 체계를 준수합니다.

선택적으로 IsBusy 속성 지원

클래스가 여러 동시 호출을 지원하지 않는 경우 속성을 노출하는 것이 IsBusy 좋습니다. 이를 통해 개발자는 MethodNameAsync 메서드에서 예외를 catch하지 않고 MethodNameAsync 메서드가 실행 중인지 여부를 확인할 수 있습니다.

IsBusy 이벤트 기반 비동기 패턴을 구현하기 위한 모범 사례에 설명된 의미 체계를 준수합니다.

필요에 따라 진행률 보고에 대한 지원 제공

비동기 작업에서 작업 중에 진행률을 보고하는 것이 바람직한 경우가 많습니다. 이벤트 기반 비동기 패턴은 이를 위한 지침을 제공합니다.

  • 필요에 따라 비동기 작업에 의해 발생하고 적절한 스레드에서 호출될 이벤트를 정의합니다. 개체는 ProgressChangedEventArgs 0에서 100 사이로 예상되는 정수 값 진행률 표시기를 전달합니다.

  • 이 이벤트의 이름을 다음과 같이 지정합니다.

    • ProgressChanged 클래스에 여러 비동기 작업이 있는 경우(또는 이후 버전에서 여러 비동기 작업을 포함하도록 증가할 것으로 예상되는 경우);

    • 클래스에 단일 비동기 작업이 있는 경우 MethodNameProgressChanged입니다.

    이 명명 선택은 선택적으로 취소 지원 섹션에 설명된 대로 취소 메서드에 대해 수행한 것과 유사합니다.

이 이벤트는 대리자 ProgressChangedEventHandler 서명 및 클래스를 ProgressChangedEventArgs 사용해야 합니다. 또는 더 많은 도메인별 진행률 표시기를 제공할 수 있는 경우(예: 다운로드 작업의 경우 바이트 읽기 및 총 바이트 수) 파생 클래스를 ProgressChangedEventArgs정의해야 합니다.

지원되는 비동기 메서드 수에 관계없이 클래스에 대해 하나 ProgressChanged 또는 MethodNameProgressChanged 이벤트만 있습니다. 클라이언트는 userStateAsync 메서드에 전달되는 개체를 사용하여 여러 동시 작업에 대한 진행률 업데이트를 구분해야 합니다.

여러 작업이 진행률을 지원하고 각각 진행률에 대해 다른 표시기를 반환하는 상황이 있을 수 있습니다. 이 경우 단일 ProgressChanged 이벤트가 적절하지 않으며 여러 ProgressChanged 이벤트를 지원하는 것이 좋습니다. 이 경우 각 MethodNameAsync 메서드에 대해 MethodNameProgressChanged의 명명 패턴을 사용합니다.

이벤트 기반 비동기 패턴을 구현하기 위한 모범 사례에 설명된 진행률 보고 의미 체계를 준수합니다.

필요에 따라 증분 결과 반환 지원 제공

경우에 따라 비동기 작업은 완료 전에 증분 결과를 반환할 수 있습니다. 이 시나리오를 지원하는 데 사용할 수 있는 다양한 옵션이 있습니다. 몇 가지 예는 다음과 같습니다.

단일 작업 클래스

클래스가 단일 비동기 작업만 지원하고 해당 작업이 증분 결과를 반환할 수 있는 경우 다음을 수행합니다.

  • ProgressChangedEventArgs 증분 결과 데이터를 전달하도록 형식을 확장하고 이 확장 데이터를 사용하여 MethodNameProgressChanged 이벤트를 정의합니다.

  • 보고할 증분 결과가 있을 때 이 MethodNameProgressChanged 이벤트를 발생시킵니다.

이 솔루션은 MethodNameProgressChanged 이벤트와 마찬가지로 "모든 작업"에서 증분 결과를 반환하기 위해 발생하는 동일한 이벤트에 문제가 없기 때문에 단일 비동기 작업 클래스에 특히 적용됩니다.

동질적인 점진적 결과가 있는 다중 작업 클래스

이 경우 클래스는 각각 증분 결과를 반환할 수 있는 여러 비동기 메서드를 지원하며 이러한 증분 결과는 모두 동일한 형식의 데이터를 갖습니다.

동일한 구조가 모든 증분 결과에 대해 작동하므로 EventArgs 단일 작업 클래스에 대해 위에서 설명한 모델을 따릅니다. ProgressChanged 여러 비동기 메서드에 적용되므로 MethodNameProgressChanged 이벤트 대신 이벤트를 정의합니다.

다양한 증분 결과가 있는 여러 가지 작업 클래스

클래스가 각각 다른 형식의 데이터를 반환하는 여러 비동기 메서드를 지원하는 경우 다음을 수행해야 합니다.

  • 증분 결과 보고를 진행률 보고와 구분합니다.

  • 각 비동기 메서드가 해당 메서드의 증분 결과 데이터를 처리하는 데 적합한 별도의 MethodNameEventArgs 이벤트를 정의합니다.

이벤트 기반 비동기 패턴 구현 모범 사례에 설명된 대로 적절한 스레드에서 해당 이벤트 처리기를 호출합니다.

메서드에서 Out 및 Ref 매개 변수 처리

.NET에서 일반적으로 outref의 사용은 권장되지 않지만, 사용 시 따라야 할 규칙은 다음과 같습니다.

동기 메서드 MethodName이 지정된 경우:

  • out MethodName에 대한 매개 변수는 MethodNameAsync의 일부가 아니어야 합니다. 대신 MethodNameCompletedEventArgsMethodName에 있는 매개 변수와 이름이 같은 부분이어야 합니다(더 적절한 이름이 없는 경우).

  • ref MethodName에 대한 매개 변수는 MethodNameAsync의 일부로 표시되고 MethodName에 해당하는 매개 변수와 이름이 같은 MethodNameCompletedEventArgs의 일부로 표시됩니다(더 적절한 이름이 없는 경우).

예를 들어 다음과 같은 조건이 있습니다.

Public Function MethodName(ByVal arg1 As String, ByRef arg2 As String, ByRef arg3 As String) As Integer
public int MethodName(string arg1, ref string arg2, out string arg3);

비동기 메서드 및 해당 AsyncCompletedEventArgs 클래스는 다음과 같습니다.

Public Sub MethodNameAsync(ByVal arg1 As String, ByVal arg2 As String)

Public Class MethodNameCompletedEventArgs
    Inherits System.ComponentModel.AsyncCompletedEventArgs
    Public ReadOnly Property Result() As Integer
    End Property
    Public ReadOnly Property Arg2() As String
    End Property
    Public ReadOnly Property Arg3() As String
    End Property
End Class
public void MethodNameAsync(string arg1, string arg2);

public class MethodNameCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
{
    public int Result { get; };
    public string Arg2 { get; };
    public string Arg3 { get; };
}

참고하십시오