연습: 이벤트 처리(Visual Basic)

이벤트를 통한 작업 방법을 보여주는 두 토픽 중 두 번째 부분입니다. 첫 번째 부분인 연습: 이벤트 선언 및 발생에서는 이벤트를 선언하는 방법과 발생시키는 방법을 보여줍니다. 이번 섹션에서는 지난 연습 때의 양식과 클래스를 사용하여 이벤트가 발생했을 때 이를 처리하는 방법을 보여줍니다.

Widget 클래스 예제는 기존의 이벤트 처리 문을 사용합니다. Visual Basic에서는 이벤트 작업을 위한 다른 기술을 제공합니다. 연습을 위해 AddHandler 문과 Handles 문을 사용할 수 있도록 이 예제를 수정하게 될 것입니다.

위젯 클래스의 PercentDone 이벤트를 처리하는 방법은 다음과 같습니다.

  1. Form1에 다음 코드를 배치합니다.

    Private WithEvents mWidget As Widget
    Private mblnCancel As Boolean
    

    WithEvents 키워드는 mWidget 변수가 개체 이벤트를 처리하는 데 사용되도록 지정합니다. 개체를 만들 클래스 이름을 제시하여 개체의 종류를 지정합니다.

    mWidget 변수는 Form1에 선언되는데, 그 이유는 WithEvents 변수가 클래스 수준이어야 하기 때문입니다. 이는 배치하는 클래스의 유형에 관계없이 마찬가지입니다.

    mblnCancel 변수는 LongTask 메서드를 취소하는 데 사용됩니다.

이벤트 처리 코드 작성

WithEvents를 이용하여 변수를 선언하는 순간, 해당 클래스의 코드 편집기 왼쪽 드롭다운 목록에 해당 변수의 이름이 표시됩니다. mWidget을 선택하면 Widget 클래스의 이벤트가 오른쪽 드롭다운 목록에 표시됩니다. 이벤트를 선택하면 해당 이벤트의 프로시저가 mWidget 접두사가 붙은 상태로 밑줄로 표시됩니다. WithEvents 변수와 관련된 모든 이벤트 프로시저에 해당 변수의 이름이 접두사로 지정됩니다.

이벤트 처리 방법은 다음과 같습니다.

  1. 코드 편집기 왼쪽 드롭다운 목록에서 mWidget을 선택합니다.

  2. 오른쪽 드롭다운 목록에서는 PercentDone 이벤트를 선택합니다. 코드 편집기mWidget_PercentDone 이벤트 프로시저를 엽니다.

    참고 항목

    코드 편집기는 유용하지만 새로운 이벤트 처리기 삽입에 필수적인 것은 아닙니다. 이번 연습에서는 이벤트 처리기를 코드에 바로 복사하는 것이 더 직접적입니다.

  3. 다음 코드를 mWidget_PercentDone 이벤트 처리기에 추가합니다.

    Private Sub mWidget_PercentDone(
        ByVal Percent As Single,
        ByRef Cancel As Boolean
    ) Handles mWidget.PercentDone
        lblPercentDone.Text = CInt(100 * Percent) & "%"
        My.Application.DoEvents()
        If mblnCancel Then Cancel = True
    End Sub
    

    PercentDone 이벤트가 발생할 때마다 이벤트 프로시저에서 Label 컨트롤에 완료 백분율을 표시합니다. DoEvents 메서드는 레이블 색상을 바꿀 수 있으며, 사용자가 취소 버튼을 클릭할 수 있도록 합니다.

  4. Button2_Click 이벤트 처리기에 다음 코드를 추가합니다.

    Private Sub Button2_Click(
        ByVal sender As Object,
        ByVal e As System.EventArgs
    ) Handles Button2.Click
        mblnCancel = True
    End Sub
    

LongTask가 실행 중일 때 사용자가 취소 단추를 클릭하면 DoEvents 문이 이벤트 처리를 허용하는 즉시 Button2_Click 이벤트가 실행됩니다. 클래스 수준의 mblnCancel 변수는 True로 설정되며, 이어서 mWidget_PercentDone 이벤트가 이를 테스트하여 ByRef Cancel 인수를 True로 설정합니다.

WithEvents 변수를 개체에 연결하기

이제 Form1이 설정되어 Widget 개체의 이벤트를 처리합니다. 남은 작업은 어딘가에 있을 Widget을 찾는 것입니다.

디자인 타임에 WithEvents 변수를 선언하면 아무 개체도 연결되어 있지 않습니다. WithEvents 변수가 다른 모든 개체 변수와 마찬가지인 상태입니다. 개체를 만든 다음 WithEvents 변수를 이용해 해당 개체에 참조를 할당해야 합니다.

개체를 만들고 참조를 할당하는 방법은 다음과 같습니다.

  1. 코드 편집기 왼쪽 드롭다운 목록에서 (Form1 이벤트)를 선택합니다.

  2. 오른쪽 드롭다운 목록에서는 Load 이벤트를 선택합니다. 코드 편집기Form1_Load 이벤트 프로시저를 엽니다.

  3. Form1_Load 이벤트 프로시저에 다음 코드를 추가하여 Widget을 만듭니다.

    Private Sub Form1_Load(
        ByVal sender As System.Object,
        ByVal e As System.EventArgs
    ) Handles MyBase.Load
        mWidget = New Widget
    End Sub
    

이 코드가 실행되면 Visual Basic에서 Widget 개체를 만들고 해당 개체의 이벤트를 mWidget에 연결된 이벤트 프로시저에 연결됩니다. 이 때부터는 WidgetPercentDone 이벤트를 발생시킬 때마다 mWidget_PercentDone 이벤트 프로시저가 실행됩니다.

LongTask 메서드를 호출하는 방법은 다음과 같습니다.

  • 다음 코드를 Button1_Click 이벤트 처리기에 추가합니다.

    Private Sub Button1_Click(
        ByVal sender As Object,
        ByVal e As System.EventArgs
    ) Handles Button1.Click
        mblnCancel = False
        lblPercentDone.Text = "0%"
        lblPercentDone.Refresh()
        mWidget.LongTask(12.2, 0.33)
        If Not mblnCancel Then lblPercentDone.Text = CStr(100) & "%"
    End Sub
    

LongTask 메서드를 호출하기 전에는 반드시 완료율(%) 표시 레이블을 초기화해야 하며 메서드 취소 관련 클래스 수준 Boolean 플래그는 반드시 False로 설정해야 합니다.

LongTask는 12.2초를 작업 기간으로 하여 호출됩니다. PercentDone 이벤트는 1/3초마다 한 번씩 발생합니다. 이벤트가 발생할 때마다 mWidget_PercentDone 이벤트 프로시저가 실행됩니다.

LongTask가 완료되면 mblnCancel을 테스트하여 LongTask가 제대로 종료되었는지, 아니면 mblnCancelTrue로 설정되어 멈췄는지 확인합니다. 완료율은 이전 사례에 대해서만 업데이트됩니다.

프로그램을 실행하려면

  1. F5 키를 눌러 프로젝트를 실행 모드로 전환합니다.

  2. 작업 시작 단추를 클릭합니다. PercentDone 이벤트가 발생할 때마다 완료된 작업 백분율로 레이블이 업데이트됩니다.

  3. 취소 단추를 클릭하여 작업을 중지합니다. 취소 단추가 표시되더라도 이를 클릭하자마자 변경되지는 않습니다. My.Application.DoEvents 문이 이벤트 처리를 허용할 때까지 Click 이벤트는 발생하지 않습니다.

    참고 항목

    My.Application.DoEvents 메서드는 양식이 이벤트를 처리하는 것과 동일한 방식으로 이벤트를 처리하지 않습니다. 예를 들어, 이번 연습에서는 취소 단추를 두 번 클릭해야 합니다. 양식이 직접 이벤트를 처리하도록 하려면 다중 스레딩을 사용하면 됩니다. 자세한 내용은 관리형 스레딩을 참조하세요.

F11 키를 사용하여 프로그램을 실행하고 코드를 한 번에 한 줄씩 실행하는 것이 바람직할 수 있습니다. 실행이 LongTask를 어떻게 입력하고, 잠시 후에 PercentDone 이벤트가 발생할 때마다 Form1을 다시 입력하는지 분명히 확인할 수 있습니다.

실행이 Form1의 코드를 다시 실행 중일 때 LongTask 메서드를 다시 호출하면 어떤 일이 발생할까요? 최악의 경우, 이벤트가 발생할 때마다 LongTask를 호출하면 스택 오버플로가 발생할 수 있습니다.

새로운 Widget에 대한 참조를 mWidget에 할당하여 mWidget 변수로 하여금 다른 Widget 개체를 처리하게 할 수 있습니다. 실제로, 단추를 클릭할 때마다 Button1_Click의 코드가 이를 매번 실행하도록 할 수 있습니다.

다른 위젯에 대한 이벤트를 처리하는 방법은 다음과 같습니다.

  • mWidget.LongTask(12.2, 0.33)인 줄 바로 앞의 Button1_Click 프로시저에 다음 코드 줄을 추가합니다.

    mWidget = New Widget
    ' Create a new Widget object.
    

위의 코드는 단추를 클릭할 때마다 새로운 Widget을 만들어 냅니다. LongTask 메서드를 완료하는 즉시 Widget에 대한 참조가 해제되고 해당 Widget은 제거됩니다.

WithEvents 변수에는 한 번에 개체 참조가 하나씩만 들어갈 수 있어서 다른 Widget 개체를 mWidget에 할당하면 이전 Widget 개체의 이벤트는 더 이상 처리되지 않습니다. mWidget이 예전 Widget에 대한 참조를 포함하는 유일한 개체 변수인 경우, 해당 개체는 제거됩니다. 여러 Widget 개체의 이벤트를 처리하려면 AddHandler 문을 사용하여 개체별로 이벤트를 각자 처리하도록 합니다.

참고 항목

WithEvents 변수는 필요한 만큼 몇 번이라도 선언할 수 있지만 WithEvents 변수의 배열은 지원하지 않습니다.

참고 항목