İzlenecek yol: Arka Plan İşlemi Kullanan Bir Form Uygulama

Tamamlanması uzun süren bir işleminiz varsa ve kullanıcı arabiriminizin (UI) yanıt vermelerini veya engellemelerini istemiyorsanız, sınıfı kullanarak işlemi başka bir iş BackgroundWorker parçacığında yürütebilirsiniz.

Bu kılavuzda, kullanıcı arabirimi yanıt verir durumda kalırken zaman alan hesaplamalar gerçekleştirmek için BackgroundWorker sınıfının nasıl "arka planda" nasıl olduğu açıklanır. bu işlemden sonra Fibonacci sayılarını zaman uyumsuz olarak hesapan bir uygulamaya sahip oluruz. Büyük bir Fibonacci sayısının hesaplanması fark edilebilir bir süre alsa da, ana kullanıcı arabirimi iş parçacığı bu gecikmeden kesintiye uğramaz ve form hesaplama sırasında yanıt verir.

Bu kılavuzda gösterilen görevler şunlardır:

  • Windows Tabanlı Uygulama Oluşturma

  • Form BackgroundWorker içinde oluşturma

  • Zaman Uyumsuz Olay İşleyicileri Ekleme

  • İptal için İlerleme Durumu Raporlama ve Destek Ekleme

Bu örnekte kullanılan kodun tam listesi için bkz. Nasıl kullanılır: Arka Plan İşlem kullanan bir Form Uygulama.

Arka plan işlemi kullanan bir form oluşturma

  1. Bu Visual Studio adlı bir Windows tabanlı uygulama projesi BackgroundWorkerExampleBackgroundWorkerExampleoluşturun ( Visual >>>>>>Project Dosya Project veya Klasik Masaüstü Visual Basic Windows Forms Uygulaması) .

  2. Bu Çözüm GezginiForm1'e sağ tıklayın ve kısayol menüsünden Yeniden Adlandır'ı seçin. Dosya adını olarak FibonacciCalculator değiştirme. '' kod öğesine yapılan tüm başvuruları yeniden adlandırmak istediğiniz sorulsa Evet düğmesine tıklayın.

  3. Araç NumericUpDown Kutusundan NumericUpDown denetim sürükleyin. özelliğini Minimum olarak, 1 özelliğini ise olarak Maximum91 ayarlayın.

  4. Forma Button iki denetim ekleyin.

  5. İlk denetimi yeniden ButtonstartAsyncButton adlandırarak özelliğini Text olarak Start Async ayarlayın. İkinci denetimi Button yeniden cancelAsyncButton adlandırarak özelliğini olarak TextCancel Async ayarlayın. özelliğini Enabled olarak false ayarlayın.

  6. Denetimlerin her iki olayı için de bir Button olay Click işleyicisi oluşturun. Ayrıntılar için, bkz. How to: Create Event Handlers Using the Designer.

  7. Araç Label kutusundan bir Label sürükleyin ve yeniden adlandırabilirsiniz. resultLabel

  8. Araç ProgressBar Kutusundan ProgressBar denetim sürükleyin.

Tasarımcı ile BackgroundWorker oluşturma

Windows Forms BackgroundWorker Tasarımcısı'nda kullanarak zaman uyumsuz BackgroundWorkeroluşturabilirsiniz.

Araç Kutusunun Bileşenler sekmesinden forma sürükleyin.

Zaman uyumsuz olay işleyicileri ekleme

Artık bileşenin zaman uyumsuz olayları için BackgroundWorker olay işleyicileri eklemeye hazır oluruz. Arka planda çalıştıracak ve Fibonacci sayılarını hesapan zaman alan işlem, bu olay işleyicilerinden biri tarafından çağrılır.

  1. Özellikler penceresinde bileşen seçiliyken Olaylar düğmesine tıklayın. Olay işleyicileri DoWork oluşturmak RunWorkerCompleted için ve olaylarını çift tıklatın. Olay işleyicilerini kullanma hakkında daha fazla bilgi için, bkz. Nasıl kullanılır: Tasarımcı Kullanarak Olay İşleyicileri Oluşturma.

  2. Form içinde adlı yeni bir ComputeFibonacci yöntem oluşturun. Bu yöntem gerçek işi yapar ve arka planda çalışır. Bu kod, Özellikle verimsiz olan Fibonacci algoritmasının özyinelemeli uygulamasını gösterir ve daha büyük sayılar için tamamlanması üstel olarak daha uzun sürer. Burada, uygulamanıza uzun gecikmeler neden olan bir işlemi göstermek amacıyla kullanılır.

    // This is the method that does the actual work. For this
    // example, it computes a Fibonacci number and
    // reports progress as it does its work.
    long ComputeFibonacci( int n, BackgroundWorker^ worker, DoWorkEventArgs ^ e )
    {
       // The parameter n must be >= 0 and <= 91.
       // Fib(n), with n > 91, overflows a long.
       if ( (n < 0) || (n > 91) )
       {
          throw gcnew ArgumentException( "value must be >= 0 and <= 91","n" );
       }
    
       long result = 0;
       
       // Abort the operation if the user has cancelled.
       // Note that a call to CancelAsync may have set 
       // CancellationPending to true just after the
       // last invocation of this method exits, so this 
       // code will not have the opportunity to set the 
       // DoWorkEventArgs.Cancel flag to true. This means
       // that RunWorkerCompletedEventArgs.Cancelled will
       // not be set to true in your RunWorkerCompleted
       // event handler. This is a race condition.
       if ( worker->CancellationPending )
       {
          e->Cancel = true;
       }
       else
       {
          if ( n < 2 )
          {
             result = 1;
          }
          else
          {
             result = ComputeFibonacci( n - 1, worker, e ) + ComputeFibonacci( n - 2, worker, e );
          }
    
          // Report progress as a percentage of the total task.
          int percentComplete = (int)((float)n / (float)numberToCompute * 100);
          if ( percentComplete > highestPercentageReached )
          {
             highestPercentageReached = percentComplete;
             worker->ReportProgress( percentComplete );
          }
       }
    
       return result;
    }
    
    // This is the method that does the actual work. For this
    // example, it computes a Fibonacci number and
    // reports progress as it does its work.
    long ComputeFibonacci(int n, BackgroundWorker worker, DoWorkEventArgs e)
    {
        // The parameter n must be >= 0 and <= 91.
        // Fib(n), with n > 91, overflows a long.
        if ((n < 0) || (n > 91))
        {
            throw new ArgumentException(
                "value must be >= 0 and <= 91", "n");
        }
    
        long result = 0;
    
        // Abort the operation if the user has canceled.
        // Note that a call to CancelAsync may have set
        // CancellationPending to true just after the
        // last invocation of this method exits, so this
        // code will not have the opportunity to set the
        // DoWorkEventArgs.Cancel flag to true. This means
        // that RunWorkerCompletedEventArgs.Cancelled will
        // not be set to true in your RunWorkerCompleted
        // event handler. This is a race condition.
    
        if (worker.CancellationPending)
        {
            e.Cancel = true;
        }
        else
        {
            if (n < 2)
            {
                result = 1;
            }
            else
            {
                result = ComputeFibonacci(n - 1, worker, e) +
                         ComputeFibonacci(n - 2, worker, e);
            }
    
            // Report progress as a percentage of the total task.
            int percentComplete =
                (int)((float)n / (float)numberToCompute * 100);
            if (percentComplete > highestPercentageReached)
            {
                highestPercentageReached = percentComplete;
                worker.ReportProgress(percentComplete);
            }
        }
    
        return result;
    }
    
    ' This is the method that does the actual work. For this
    ' example, it computes a Fibonacci number and
    ' reports progress as it does its work.
    Function ComputeFibonacci( _
        ByVal n As Integer, _
        ByVal worker As BackgroundWorker, _
        ByVal e As DoWorkEventArgs) As Long
    
        ' The parameter n must be >= 0 and <= 91.
        ' Fib(n), with n > 91, overflows a long.
        If n < 0 OrElse n > 91 Then
            Throw New ArgumentException( _
                "value must be >= 0 and <= 91", "n")
        End If
    
        Dim result As Long = 0
    
        ' Abort the operation if the user has canceled.
        ' Note that a call to CancelAsync may have set 
        ' CancellationPending to true just after the
        ' last invocation of this method exits, so this 
        ' code will not have the opportunity to set the 
        ' DoWorkEventArgs.Cancel flag to true. This means
        ' that RunWorkerCompletedEventArgs.Cancelled will
        ' not be set to true in your RunWorkerCompleted
        ' event handler. This is a race condition.
        If worker.CancellationPending Then
            e.Cancel = True
        Else
            If n < 2 Then
                result = 1
            Else
                result = ComputeFibonacci(n - 1, worker, e) + _
                         ComputeFibonacci(n - 2, worker, e)
            End If
    
            ' Report progress as a percentage of the total task.
            Dim percentComplete As Integer = _
                CSng(n) / CSng(numberToCompute) * 100
            If percentComplete > highestPercentageReached Then
                highestPercentageReached = percentComplete
                worker.ReportProgress(percentComplete)
            End If
    
        End If
    
        Return result
    
    End Function
    
  3. Olay DoWork işleyicisinde yöntemine bir çağrı ComputeFibonacci ekleyin. özelliğinin ilk ComputeFibonacciArgument parametresini DoWorkEventArgs alır. ve BackgroundWorker parametreleri daha sonra ilerleme raporlama ve iptal desteği için DoWorkEventArgs kullanılacaktır. değerinden dönüş değerini ComputeFibonacciResult özelliğinin özelliğine attayabilirsiniz. DoWorkEventArgs Bu sonuç olay işleyicisi RunWorkerCompleted tarafından kullanılabilir.

    Not

    Olay işleyicisi örnek değişkenine doğrudan başvurur çünkü bu olay işleyicisini belirli DoWorkbackgroundWorker1 bir örneğine bağlı olarak BackgroundWorker kullanabilirsiniz. Bunun yerine, bu BackgroundWorker olayı yükselten başvurusu parametresinden sender kurtarıldı. Bu, form birden fazla barındırarak BackgroundWorker önemlidir. Olay işleyicisi içinde kullanıcı arabirimi nesnelerini DoWork işlemeyebilirsiniz. Bunun yerine, olaylar aracılığıyla kullanıcı arabirimiyle iletişim BackgroundWorker kurar.

    // This event handler is where the actual,
    // potentially time-consuming work is done.
    void backgroundWorker1_DoWork( Object^ sender, DoWorkEventArgs^ e )
    {
       // Get the BackgroundWorker that raised this event.
       BackgroundWorker^ worker = dynamic_cast<BackgroundWorker^>(sender);
    
       // Assign the result of the computation
       // to the Result property of the DoWorkEventArgs
       // object. This is will be available to the 
       // RunWorkerCompleted eventhandler.
       e->Result = ComputeFibonacci( safe_cast<Int32>(e->Argument), worker, e );
    }
    
    // This event handler is where the actual,
    // potentially time-consuming work is done.
    private void backgroundWorker1_DoWork(object sender,
        DoWorkEventArgs e)
    {
        // Get the BackgroundWorker that raised this event.
        BackgroundWorker worker = sender as BackgroundWorker;
    
        // Assign the result of the computation
        // to the Result property of the DoWorkEventArgs
        // object. This is will be available to the
        // RunWorkerCompleted eventhandler.
        e.Result = ComputeFibonacci((int)e.Argument, worker, e);
    }
    
    ' This event handler is where the actual work is done.
    Private Sub backgroundWorker1_DoWork( _
    ByVal sender As Object, _
    ByVal e As DoWorkEventArgs) _
    Handles backgroundWorker1.DoWork
    
        ' Get the BackgroundWorker object that raised this event.
        Dim worker As BackgroundWorker = _
            CType(sender, BackgroundWorker)
    
        ' Assign the result of the computation
        ' to the Result property of the DoWorkEventArgs
        ' object. This is will be available to the 
        ' RunWorkerCompleted eventhandler.
        e.Result = ComputeFibonacci(e.Argument, worker, e)
    End Sub
    
  4. Denetimin startAsyncButton olay Click işleyicisinde, zaman uyumsuz işlemi başlatan kodu ekleyin.

    void startAsyncButton_Click( System::Object^ /*sender*/, System::EventArgs^ /*e*/ )
    {
       
       // Reset the text in the result label.
       resultLabel->Text = String::Empty;
    
       // Disable the UpDown control until 
       // the asynchronous operation is done.
       this->numericUpDown1->Enabled = false;
    
       // Disable the Start button until 
       // the asynchronous operation is done.
       this->startAsyncButton->Enabled = false;
    
       // Enable the Cancel button while 
       // the asynchronous operation runs.
       this->cancelAsyncButton->Enabled = true;
    
       // Get the value from the UpDown control.
       numberToCompute = (int)numericUpDown1->Value;
    
       // Reset the variable for percentage tracking.
       highestPercentageReached = 0;
    
       // Start the asynchronous operation.
       backgroundWorker1->RunWorkerAsync( numberToCompute );
    }
    
    private void startAsyncButton_Click(System.Object sender,
        System.EventArgs e)
    {
        // Reset the text in the result label.
        resultLabel.Text = String.Empty;
    
        // Disable the UpDown control until
        // the asynchronous operation is done.
        this.numericUpDown1.Enabled = false;
    
        // Disable the Start button until
        // the asynchronous operation is done.
        this.startAsyncButton.Enabled = false;
    
        // Enable the Cancel button while
        // the asynchronous operation runs.
        this.cancelAsyncButton.Enabled = true;
    
        // Get the value from the UpDown control.
        numberToCompute = (int)numericUpDown1.Value;
    
        // Reset the variable for percentage tracking.
        highestPercentageReached = 0;
    
        // Start the asynchronous operation.
        backgroundWorker1.RunWorkerAsync(numberToCompute);
    }
    
    Private Sub startAsyncButton_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) _
    Handles startAsyncButton.Click
    
        ' Reset the text in the result label.
        resultLabel.Text = [String].Empty
    
        ' Disable the UpDown control until 
        ' the asynchronous operation is done.
        Me.numericUpDown1.Enabled = False
    
        ' Disable the Start button until 
        ' the asynchronous operation is done.
        Me.startAsyncButton.Enabled = False
    
        ' Enable the Cancel button while 
        ' the asynchronous operation runs.
        Me.cancelAsyncButton.Enabled = True
    
        ' Get the value from the UpDown control.
        numberToCompute = CInt(numericUpDown1.Value)
    
        ' Reset the variable for percentage tracking.
        highestPercentageReached = 0
    
    
        ' Start the asynchronous operation.
        backgroundWorker1.RunWorkerAsync(numberToCompute)
    End Sub 
    
  5. Olay RunWorkerCompleted işleyicisinde, hesaplamanın sonucu denetimine resultLabel attayn.

    // This event handler deals with the results of the
    // background operation.
    void backgroundWorker1_RunWorkerCompleted( Object^ /*sender*/, RunWorkerCompletedEventArgs^ e )
    {
       // First, handle the case where an exception was thrown.
       if ( e->Error != nullptr )
       {
          MessageBox::Show( e->Error->Message );
       }
       else
       if ( e->Cancelled )
       {
          // Next, handle the case where the user cancelled 
          // the operation.
          // Note that due to a race condition in 
          // the DoWork event handler, the Cancelled
          // flag may not have been set, even though
          // CancelAsync was called.
          resultLabel->Text = "Cancelled";
       }
       else
       {
          // Finally, handle the case where the operation 
          // succeeded.
          resultLabel->Text = e->Result->ToString();
       }
    
       // Enable the UpDown control.
       this->numericUpDown1->Enabled = true;
    
       // Enable the Start button.
       startAsyncButton->Enabled = true;
    
       // Disable the Cancel button.
       cancelAsyncButton->Enabled = false;
    }
    
    // This event handler deals with the results of the
    // background operation.
    private void backgroundWorker1_RunWorkerCompleted(
        object sender, RunWorkerCompletedEventArgs e)
    {
        // First, handle the case where an exception was thrown.
        if (e.Error != null)
        {
            MessageBox.Show(e.Error.Message);
        }
        else if (e.Cancelled)
        {
            // Next, handle the case where the user canceled
            // the operation.
            // Note that due to a race condition in
            // the DoWork event handler, the Cancelled
            // flag may not have been set, even though
            // CancelAsync was called.
            resultLabel.Text = "Canceled";
        }
        else
        {
            // Finally, handle the case where the operation
            // succeeded.
            resultLabel.Text = e.Result.ToString();
        }
    
        // Enable the UpDown control.
        this.numericUpDown1.Enabled = true;
    
        // Enable the Start button.
        startAsyncButton.Enabled = true;
    
        // Disable the Cancel button.
        cancelAsyncButton.Enabled = false;
    }
    
    ' This event handler deals with the results of the
    ' background operation.
    Private Sub backgroundWorker1_RunWorkerCompleted( _
    ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) _
    Handles backgroundWorker1.RunWorkerCompleted
    
        ' First, handle the case where an exception was thrown.
        If (e.Error IsNot Nothing) Then
            MessageBox.Show(e.Error.Message)
        ElseIf e.Cancelled Then
            ' Next, handle the case where the user canceled the 
            ' operation.
            ' Note that due to a race condition in 
            ' the DoWork event handler, the Cancelled
            ' flag may not have been set, even though
            ' CancelAsync was called.
            resultLabel.Text = "Canceled"
        Else
            ' Finally, handle the case where the operation succeeded.
            resultLabel.Text = e.Result.ToString()
        End If
    
        ' Enable the UpDown control.
        Me.numericUpDown1.Enabled = True
    
        ' Enable the Start button.
        startAsyncButton.Enabled = True
    
        ' Disable the Cancel button.
        cancelAsyncButton.Enabled = False
    End Sub
    

İptal için İlerleme Durumu Raporlama ve Destek Ekleme

Uzun süren zaman uyumsuz işlemler için genellikle ilerlemeyi kullanıcıya bildirmeniz ve kullanıcının işlemi iptal etmelerine izin vermek tercih edilir. sınıfı, BackgroundWorker arka plan işlemi devam ettikçe ilerleme durumuyla karşılaşmanıza olanak sağlayan bir olay sağlar. Ayrıca, çalışan kodunuzun çağrısı algılamasını ve kendisini kesintiye uğratmasını sağlayan CancelAsync bir bayrak da sağlar.

İlerleme durumu raporlamayı uygulama

  1. Özellikler penceresindeöğesini seçin. WorkerReportsProgress ve WorkerSupportsCancellation özelliklerini true olarak ayarlayın.

  2. Formda iki değişken FibonacciCalculator bildir. Bunlar ilerlemeyi izlemek için kullanılır.

    int numberToCompute;
    int highestPercentageReached;
    
    private int numberToCompute = 0;
    private int highestPercentageReached = 0;
    
    Private numberToCompute As Integer = 0
    Private highestPercentageReached As Integer = 0
    
  3. Olay için bir olay ProgressChanged işleyicisi ekleyin. Olay ProgressChanged işleyicisinde ProgressBar parametresinin ProgressPercentage özelliğiyle ProgressChangedEventArgs güncelleştirin.

    // This event handler updates the progress bar.
    void backgroundWorker1_ProgressChanged( Object^ /*sender*/, ProgressChangedEventArgs^ e )
    {
       this->progressBar1->Value = e->ProgressPercentage;
    }
    
    // This event handler updates the progress bar.
    private void backgroundWorker1_ProgressChanged(object sender,
        ProgressChangedEventArgs e)
    {
        this.progressBar1.Value = e.ProgressPercentage;
    }
    
    ' This event handler updates the progress bar.
    Private Sub backgroundWorker1_ProgressChanged( _
    ByVal sender As Object, ByVal e As ProgressChangedEventArgs) _
    Handles backgroundWorker1.ProgressChanged
    
        Me.progressBar1.Value = e.ProgressPercentage
    
    End Sub
    

İptal için destek uygulama

  1. Denetimin cancelAsyncButton olay Click işleyicisinde, zaman uyumsuz işlemi iptal etmek için kodu ekleyin.

    void cancelAsyncButton_Click( System::Object^ /*sender*/, System::EventArgs^ /*e*/ )
    {  
       // Cancel the asynchronous operation.
       this->backgroundWorker1->CancelAsync();
       
       // Disable the Cancel button.
       cancelAsyncButton->Enabled = false;
    }
    
    private void cancelAsyncButton_Click(System.Object sender,
        System.EventArgs e)
    {
        // Cancel the asynchronous operation.
        this.backgroundWorker1.CancelAsync();
    
        // Disable the Cancel button.
        cancelAsyncButton.Enabled = false;
    }
    
    Private Sub cancelAsyncButton_Click( _
    ByVal sender As System.Object, _
    ByVal e As System.EventArgs) _
    Handles cancelAsyncButton.Click
        
        ' Cancel the asynchronous operation.
        Me.backgroundWorker1.CancelAsync()
    
        ' Disable the Cancel button.
        cancelAsyncButton.Enabled = False
        
    End Sub
    
  2. Yöntemde yer alan aşağıdaki kod parçaları ComputeFibonacci ilerleme durumu rapor eder ve iptali destekler.

    if ( worker->CancellationPending )
    {
       e->Cancel = true;
    }
    
    if (worker.CancellationPending)
    {
        e.Cancel = true;
    }
    
    If worker.CancellationPending Then
        e.Cancel = True
    
    // Report progress as a percentage of the total task.
    int percentComplete = (int)((float)n / (float)numberToCompute * 100);
    if ( percentComplete > highestPercentageReached )
    {
       highestPercentageReached = percentComplete;
       worker->ReportProgress( percentComplete );
    }
    
    // Report progress as a percentage of the total task.
    int percentComplete =
        (int)((float)n / (float)numberToCompute * 100);
    if (percentComplete > highestPercentageReached)
    {
        highestPercentageReached = percentComplete;
        worker.ReportProgress(percentComplete);
    }
    
    ' Report progress as a percentage of the total task.
    Dim percentComplete As Integer = _
        CSng(n) / CSng(numberToCompute) * 100
    If percentComplete > highestPercentageReached Then
        highestPercentageReached = percentComplete
        worker.ReportProgress(percentComplete)
    End If
    

Checkpoint

Bu noktada Fibonacci Hesaplayıcısı uygulamasını derler ve çalıştırabilirsiniz.

Uygulamayı derlemek ve çalıştırmak için F5 tuşuna basın.

Hesaplama arka planda çalışırken, hesaplamanın tamamlanmaya ProgressBar doğru ilerlemesini gösteren bir görüntü görüntülenir. Bekleyen işlemi de iptal edebilirsiniz.

Küçük sayılar için hesaplama çok hızlı olmalı, ancak daha büyük sayılar için fark edilebilir bir gecikme görüyor gerekir. 30 veya daha büyük bir değer girersiniz, bilgisayarınızın hızına bağlı olarak birkaç saniyelik bir gecikmeyle karşınıza gerekir. 40'dan büyük değerler için hesaplamanın tamamlanması dakika veya saat sürebilir. Hesap makinesi büyük bir Fibonacci sayısını hesaplamayla meşgul olsa da, formu serbestçe hareket ettirebilirsiniz, simge durumuna küçültebilirsiniz, ekranı kaplar ve hatta çıkarabilirsiniz. Bunun nedeni, ana kullanıcı arabirimi iş parçacığının hesaplamanın tamamlanması için beklemesi değildir.

Sonraki adımlar

Artık bir bileşeni kullanarak arka planda hesaplama yürüten bir form uygulamaya başladınız, zaman uyumsuz işlemler için diğer BackgroundWorker olasılıkları keşfedebilirsiniz:

Ayrıca bkz.