Поделиться через


Пример. Фоновое выполнение операции

Обновлен: Ноябрь 2007

Если какая-либо операция будет выполняться в течение долгого времени, и при этом требуется не допустить, чтобы пользовательский интерфейс перестал отвечать на запросы пользователя или "завис", можно использовать класс BackgroundWorker для выполнения операции в другом потоке.

Полный текст кода для текущего примера см. в разделе Практическое руководство. Фоновое выполнение операции.

ms233672.alert_note(ru-ru,VS.90).gifПримечание.

Отображаемые диалоговые окна и команды меню могут отличаться от описанных в справке в зависимости от текущих настроек или выпуска среды. Для изменения настроек выберите Импорт и экспорт параметров в меню Сервис. Дополнительные сведения см. в разделе Параметры Visual Studio.

Для запуска операции в фоновом режиме выполните следующие действия.

  1. Когда форма будет открыта в конструкторе Windows Forms, перетащите два элемента управления Button с панели элементов в форму, затем установите значения свойств Name и Text для кнопок согласно следующей таблицы.

    Кнопка

    Название

    Текст

    button1

    startBtn

    Пуск

    button2

    cancelBtn

    Отмена

  2. Откройте панель элементов, перейдите на вкладку Компоненты и перетащите в форму компонент BackgroundWorker.

    Компонент backgroundWorker1 появится в области компонентов.

  3. В окне Свойства нажмите кнопку События, и затем дважды щелкните события DoWork и RunWorkerCompleted, чтобы создать обработчики событий.

  4. Вставьте код, требующий длительного выполнения, в обработчик события DoWork.

  5. Параметры, необходимые для операции, можно получить из свойства Argument параметра DoWorkEventArgs.

  6. Присвойте результат вычисления свойству ResultDoWorkEventArgs.

    Результат будет доступен для обработчика событий RunWorkerCompleted.

    Private Sub backgroundWorker1_DoWork( _
    sender As Object, e As DoWorkEventArgs) _
    Handles backgroundWorker1.DoWork
    
       ' Do not access the form's BackgroundWorker reference directly.
       ' Instead, use the reference provided by the sender parameter.
       Dim bw As BackgroundWorker = CType( sender, BackgroundWorker )
    
       ' Extract the argument.
       Dim arg As Integer = Fix(e.Argument)
    
       ' Start the time-consuming operation.
       e.Result = TimeConsumingOperation(bw, arg)
    
       ' If the operation was canceled by the user, 
       ' set the DoWorkEventArgs.Cancel property to true.
       If bw.CancellationPending Then
          e.Cancel = True
       End If
    
    End Sub   
    
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        // Do not access the form's BackgroundWorker reference directly.
        // Instead, use the reference provided by the sender parameter.
        BackgroundWorker bw = sender as BackgroundWorker;
    
        // Extract the argument.
        int arg = (int)e.Argument;
    
        // Start the time-consuming operation.
        e.Result = TimeConsumingOperation(bw, arg);
    
        // If the operation was canceled by the user, 
        // set the DoWorkEventArgs.Cancel property to true.
        if (bw.CancellationPending)
        {
            e.Cancel = true;
        }
    }
    
  7. Вставьте код для получения результата операции в обработчик события RunWorkerCompleted.

    ' This event handler demonstrates how to interpret 
    ' the outcome of the asynchronous operation implemented
    ' in the DoWork event handler.
    Private Sub backgroundWorker1_RunWorkerCompleted( _
    sender As Object, e As RunWorkerCompletedEventArgs) _
    Handles backgroundWorker1.RunWorkerCompleted
    
       If e.Cancelled Then
          ' The user canceled the operation.
          MessageBox.Show("Operation was canceled")
       ElseIf (e.Error IsNot Nothing) Then
          ' There was an error during the operation.
          Dim msg As String = String.Format("An error occurred: {0}", e.Error.Message)
          MessageBox.Show(msg)
       Else
          ' The operation completed normally.
          Dim msg As String = String.Format("Result = {0}", e.Result)
          MessageBox.Show(msg)
       End If
    End Sub   
    
    // This event handler demonstrates how to interpret 
    // the outcome of the asynchronous operation implemented
    // in the DoWork event handler.
    private void backgroundWorker1_RunWorkerCompleted(
        object sender, 
        RunWorkerCompletedEventArgs e)
    {   
        if (e.Cancelled)
        {
            // The user canceled the operation.
            MessageBox.Show("Operation was canceled");
        }
        else if (e.Error != null)
        {
            // There was an error during the operation.
            string msg = String.Format("An error occurred: {0}", e.Error.Message);
            MessageBox.Show(msg);
        }
        else
        {
            // The operation completed normally.
            string msg = String.Format("Result = {0}", e.Result);
            MessageBox.Show(msg);
        }
    }
    
  8. Реализуйте метод TimeConsumingOperation.

    ' This method models an operation that may take a long time 
    ' to run. It can be cancelled, it can raise an exception,
    ' or it can exit normally and return a result. These outcomes
    ' are chosen randomly.
    Private Function TimeConsumingOperation( _
    bw As BackgroundWorker, _
    sleepPeriod As Integer) As Integer
    
       Dim result As Integer = 0
    
       Dim rand As New Random()
    
         While Not bw.CancellationPending
             Dim [exit] As Boolean = False
    
             Select Case rand.Next(3)
                 ' Raise an exception.
                 Case 0
                     Throw New Exception("An error condition occurred.")
                     Exit While
    
                     ' Sleep for the number of milliseconds
                     ' specified by the sleepPeriod parameter.
                 Case 1
                     Thread.Sleep(sleepPeriod)
                     Exit While
    
                     ' Exit and return normally.
                 Case 2
                     result = 23
                     [exit] = True
                     Exit While
    
                 Case Else
                     Exit While
             End Select
    
             If [exit] Then
                 Exit While
             End If
         End While
    
       Return result
    End Function
    
    // This method models an operation that may take a long time 
    // to run. It can be cancelled, it can raise an exception,
    // or it can exit normally and return a result. These outcomes
    // are chosen randomly.
    private int TimeConsumingOperation( 
        BackgroundWorker bw, 
        int sleepPeriod )
    {
        int result = 0;
    
        Random rand = new Random();
    
        while (!bw.CancellationPending)
        {
            bool exit = false;
    
            switch (rand.Next(3))
            {
                // Raise an exception.
                case 0:
                {
                    throw new Exception("An error condition occurred.");
                    break;
                }
    
                // Sleep for the number of milliseconds
                // specified by the sleepPeriod parameter.
                case 1:
                {
                    Thread.Sleep(sleepPeriod);
                    break;
                }
    
                // Exit and return normally.
                case 2:
                {
                    result = 23;
                    exit = true;
                    break;
                }
    
                default:
                {
                    break;
                }
            }
    
            if( exit )
            {
                break;
            }
        }
    
        return result;
    }
    
  9. В конструкторе Windows Forms дважды щелкните startButton, чтобы создать обработчик события Click.

  10. Вызовите метод RunWorkerAsync в обработчике событий Click для startButton.

    Private Sub startButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles startBtn.Click
        Me.backgroundWorker1.RunWorkerAsync(2000)
    End Sub
    
    private void startBtn_Click(object sender, EventArgs e)
    {
        this.backgroundWorker1.RunWorkerAsync(2000);
    }
    
  11. В конструкторе Windows Forms дважды щелкните cancelButton, чтобы создать обработчик события Click.

  12. Вызовите метод CancelAsync в обработчике событий Click для cancelButton.

    Private Sub cancelButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles cancelBtn.Click
        Me.backgroundWorker1.CancelAsync()
    End Sub
    
    private void cancelBtn_Click(object sender, EventArgs e)
    {
        this.backgroundWorker1.CancelAsync();
    }
    
  13. В начале файла импортируйте пространства имен System.ComponentModel и System.Threading.

    Imports System
    Imports System.ComponentModel
    Imports System.Drawing
    Imports System.Threading
    Imports System.Windows.Forms
    
    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Threading;
    using System.Windows.Forms;
    
  14. Нажмите клавишу F6 Press для построения решения, затем нажмите клавиши CTRL-F5 для запуска приложения вне отладчика.

ms233672.alert_note(ru-ru,VS.90).gifПримечание.

Если нажать клавишу F5 и запустить приложение в отладчике, то исключение, возникающее в методе TimeConsumingOperation, перехватывается и отображается отладчиком. При запуске приложения вне отладчика BackgroundWorker обрабатывает исключение и кэширует его в свойстве ErrorRunWorkerCompletedEventArgs.

  1. Нажмите кнопку Пуск для запуска асинхронной операции, затем нажмите кнопку Отмена для ее остановки.

    Результат каждой операции отображается в MessageBox.

Следующие действия

См. также

Задачи

Практическое руководство. Реализация формы, в которой выполняется фоновая операция

Практическое руководство. Фоновое выполнение операции

Ссылки

BackgroundWorker

DoWorkEventArgs

Другие ресурсы

Компонент BackgroundWorker