Пошаговое руководство. Обработка событий (Visual Basic)Walkthrough: Handling Events (Visual Basic)

Это второй из двух разделов, демонстрирующих работу с событиями.This is the second of two topics that demonstrate how to work with events. В первом разделе Пошаговое руководство. объявление и создание событийпоказано, как объявлять и создавать события.The first topic, Walkthrough: Declaring and Raising Events, shows how to declare and raise events. В этом разделе используется форма и класс из этого пошагового руководства, чтобы продемонстрировать, как обрабатывались события, когда они выполняются.This section uses the form and class from that walkthrough to show how to handle events when they take place.

В примере класса Widget используются традиционные инструкции по обработке событий.The Widget class example uses traditional event-handling statements. Visual Basic предоставляет другие методы для работы с событиями.Visual Basic provides other techniques for working with events. В качестве упражнения можно изменить этот пример, чтобы использовать инструкции AddHandler и Handles.As an exercise, you can modify this example to use the AddHandler and Handles statements.

Для управления событием PercentDone класса WidgetTo handle the PercentDone event of the Widget class

  1. Поместите следующий код в Form1:Place the following code in Form1:

    Private WithEvents mWidget As Widget
    Private mblnCancel As Boolean
    

    Ключевое слово WithEvents указывает, что переменная mWidget используется для управления событиями объекта.The WithEvents keyword specifies that the variable mWidget is used to handle an object's events. Тип объекта указывается путем указания имени класса, из которого будет создан объект.You specify the kind of object by supplying the name of the class from which the object will be created.

    Переменная mWidget объявляется в Form1, так как переменные WithEvents должны быть уровня класса.The variable mWidget is declared in Form1 because WithEvents variables must be class-level. Это справедливо независимо от типа класса, в котором они размещены.This is true regardless of the type of class you place them in.

    Переменная mblnCancel используется для отмены метода LongTask.The variable mblnCancel is used to cancel the LongTask method.

Написание кода для обработчика событияWriting Code to Handle an Event

Как только вы объявили переменную с помощью WithEvents, имя переменной отображается в левом раскрывающемся списке редактора кодакласса.As soon as you declare a variable using WithEvents, the variable name appears in the left drop-down list of the class's Code Editor. При выборе mWidgetсобытия класса Widget отображаются в правом раскрывающемся списке.When you select mWidget, the Widget class's events appear in the right drop-down list. При выборе события отображается соответствующая процедура события с префиксом mWidget и символом подчеркивания.Selecting an event displays the corresponding event procedure, with the prefix mWidget and an underscore. Всем процедурам события, связанным с переменной WithEvents, присваивается имя переменной в виде префикса.All the event procedures associated with a WithEvents variable are given the variable name as a prefix.

Чтобы обработать событиеTo handle an event

  1. Выберите mWidget из раскрывающегося списка слева в редакторе кода.Select mWidget from the left drop-down list in the Code Editor.

  2. Выберите событие PercentDone из раскрывающегося списка справа.Select the PercentDone event from the right drop-down list. Редактор кода открывает процедуру mWidget_PercentDone события.The Code Editor opens the mWidget_PercentDone event procedure.

    Примечание

    Редактор кода удобен, но не является обязательным для вставки новых обработчиков событий.The Code Editor is useful, but not required, for inserting new event handlers. В этом пошаговом руководстве более прямым просто скопировать обработчики событий непосредственно в код.In this walkthrough, it is more direct to just copy the event handlers directly into your code.

  3. Добавьте следующий код в обработчик событий mWidget_PercentDone .Add the following code to the mWidget_PercentDone event handler:

    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.Whenever the PercentDone event is raised, the event procedure displays the percent complete in a Label control. Метод DoEvents позволяет перекрасить метку, а также дает пользователю возможность нажать кнопку Отмена .The DoEvents method allows the label to repaint, and also gives the user the opportunity to click the Cancel button.

  4. Добавьте следующий код для обработчика событий Button2_Click:Add the following code for the Button2_Click event handler:

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

Если пользователь нажимает кнопку Отмена во время выполнения LongTask, событие Button2_Click выполняется, как только инструкция DoEvents разрешает обработку события.If the user clicks the Cancel button while LongTask is running, the Button2_Click event is executed as soon as the DoEvents statement allows event processing to occur. Переменная уровня класса mblnCancel имеет значение True, а событие mWidget_PercentDone проверяет его и задает для аргумента ByRef Cancel значение True.The class-level variable mblnCancel is set to True, and the mWidget_PercentDone event then tests it and sets the ByRef Cancel argument to True.

Подключение переменной WithEvents к объектуConnecting a WithEvents Variable to an Object

Form1 теперь настроен на обработку событий объекта Widget.Form1 is now set up to handle a Widget object's events. Все, что остается, — найти Widget где-нибудь.All that remains is to find a Widget somewhere.

При объявлении переменной WithEvents во время разработки ни один из объектов не связан с ним.When you declare a variable WithEvents at design time, no object is associated with it. WithEvents переменная аналогична любой другой объектной переменной.A WithEvents variable is just like any other object variable. Необходимо создать объект и присвоить ему ссылку на переменную WithEvents.You have to create an object and assign a reference to it with the WithEvents variable.

Создание объекта и присвоение ему ссылкиTo create an object and assign a reference to it

  1. Выберите (события Form1) в левом раскрывающемся списке в редакторе кода.Select (Form1 Events) from the left drop-down list in the Code Editor.

  2. Выберите событие Load из раскрывающегося списка справа.Select the Load event from the right drop-down list. Редактор кода открывает процедуру Form1_Load события.The Code Editor opens the Form1_Load event procedure.

  3. Добавьте следующий код для процедуры Form1_Load события, чтобы создать Widget:Add the following code for the Form1_Load event procedure to create the 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.When this code executes, Visual Basic creates a Widget object and connects its events to the event procedures associated with mWidget. С этого момента каждый раз, когда Widget вызывает событие PercentDone, выполняется процедура mWidget_PercentDone события.From that point on, whenever the Widget raises its PercentDone event, the mWidget_PercentDone event procedure is executed.

Вызов метода LongTaskTo call the LongTask method

  • Добавьте следующий код в обработчик событий Button1_Click .Add the following code to the Button1_Click event handler:

    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.Before the LongTask method is called, the label that displays the percent complete must be initialized, and the class-level Boolean flag for canceling the method must be set to False.

LongTask вызывается с длительностью задачи в 12,2 секунд.LongTask is called with a task duration of 12.2 seconds. Событие PercentDone возникает один раз в секунду.The PercentDone event is raised once every one-third of a second. При каждом возникновении события выполняется процедура mWidget_PercentDone события.Each time the event is raised, the mWidget_PercentDone event procedure is executed.

Когда LongTask, mblnCancel тестируется, чтобы узнать, завершился ли LongTask в обычном режиме или остановлена, так как для mblnCancel было установлено значение True.When LongTask is done, mblnCancel is tested to see if LongTask ended normally, or if it stopped because mblnCancel was set to True. Процент завершения обновляется только в первом случае.The percent complete is updated only in the former case.

Чтобы выполнить программу, выполните следующие действия.To run the program

  1. Нажмите клавишу F5, чтобы перевести проект в режим выполнения.Press F5 to put the project in run mode.

  2. Нажмите кнопку запустить задачу .Click the Start Task button. При каждом возникновении события PercentDone метка обновляется в процентах от завершенной задачи.Each time the PercentDone event is raised, the label is updated with the percentage of the task that is complete.

  3. Нажмите кнопку Отмена , чтобы остановить задачу.Click the Cancel button to stop the task. Обратите внимание, что внешний вид кнопки Отмена не меняется сразу же после нажатия.Notice that the appearance of the Cancel button does not change immediately when you click it. Событие Click не может произойти, пока инструкция My.Application.DoEvents не разрешит обработку событий.The Click event cannot happen until the My.Application.DoEvents statement allows event processing.

    Примечание

    Метод My.Application.DoEvents не обрабатывает события точно так же, как и форма.The My.Application.DoEvents method does not process events in exactly the same way as the form does. Например, в этом пошаговом руководстве необходимо дважды нажать кнопку Отмена .For example, in this walkthrough, you must click the Cancel button twice. Чтобы форма могла напрямую управлять событиями, можно использовать многопоточность.To allow the form to handle the events directly, you can use multithreading. Дополнительные сведения см. в разделе управляемые потоки.For more information, see Managed Threading.

Может оказаться полезным запустить программу с помощью F11 и пошаговое выполнение кода.You may find it instructive to run the program with F11 and step through the code a line at a time. Вы можете ясно видеть, как выполнение переходит LongTask, а затем ненадолго переводит Form1 каждый раз при возникновении события PercentDone.You can clearly see how execution enters LongTask, and then briefly re-enters Form1 each time the PercentDone event is raised.

Что произойдет, если при завершении выполнения кода Form1метод LongTask был вызван повторно?What would happen if, while execution was back in the code of Form1, the LongTask method were called again? В худшем случае может произойти переполнение стека, если LongTask вызывались каждый раз при возникновении события.At worst, a stack overflow might occur if LongTask were called every time the event was raised.

Можно сделать так, чтобы переменная mWidget обрабатывала события для другого Widget объекта, назначив для mWidgetссылку на новую Widget.You can cause the variable mWidget to handle events for a different Widget object by assigning a reference to the new Widget to mWidget. На самом деле можно сделать код в Button1_Click делать это при каждом нажатии кнопки.In fact, you can make the code in Button1_Click do this every time you click the button.

Для управления событиями для другого мини-приложенияTo handle events for a different widget

  • Добавьте следующую строку кода в процедуру Button1_Click, непосредственно перед строкой, считывающей mWidget.LongTask(12.2, 0.33):Add the following line of code to the Button1_Click procedure, immediately preceding the line that reads mWidget.LongTask(12.2, 0.33):

    mWidget = New Widget
    ' Create a new Widget object.
    

Приведенный выше код создает новый Widget каждый раз при нажатии кнопки.The code above creates a new Widget each time the button is clicked. После завершения метода LongTask ссылка на Widget освобождается, а Widget уничтожается.As soon as the LongTask method completes, the reference to the Widget is released, and the Widget is destroyed.

WithEvents переменная может содержать только одну ссылку на объект за раз, поэтому, если вы назначите другой объект Widget для mWidget, события предыдущего Widget объекта больше не будут обрабатываться.A WithEvents variable can contain only one object reference at a time, so if you assign a different Widget object to mWidget, the previous Widget object's events will no longer be handled. Если mWidget является единственной объектной переменной, содержащей ссылку на старую Widget, объект уничтожается.If mWidget is the only object variable containing a reference to the old Widget, the object is destroyed. Если требуется обрабатывать события из нескольких Widget объектов, используйте инструкцию AddHandler для обработки событий каждого объекта отдельно.If you want to handle events from several Widget objects, use the AddHandler statement to process events from each object separately.

Примечание

Можно объявить столько WithEvents переменных, сколько требуется, но массивы WithEvents переменных не поддерживаются.You can declare as many WithEvents variables as you need, but arrays of WithEvents variables are not supported.

См. такжеSee also