`
bolutes
  • 浏览: 868724 次
文章分类
社区版块
存档分类
最新评论

如何:实现使用后台操作的窗体

 
阅读更多

下面的程序示例创建了一个计算 Fibonacci 数的窗体。该计算运行于用户界面线程之外的另一个线程上,因此用户界面可在计算进行的同时继续运行,而不会出现延迟。

Visual Studio 中对此任务提供了广泛的支持。

有关更多信息,请参见演练:实现一个使用后台操作的窗体

示例

Visual Basic
Imports System
Imports System.Collections
Imports System.ComponentModel
Imports System.Drawing
Imports System.Threading
Imports System.Windows.Forms

Public Class FibonacciForm
    Inherits System.Windows.Forms.Form

    Private numberToCompute As Integer = 0
    Private highestPercentageReached As Integer = 0

    Private numericUpDown1 As System.Windows.Forms.NumericUpDown
    Private WithEvents startAsyncButton As System.Windows.Forms.Button
    Private WithEvents cancelAsyncButton As System.Windows.Forms.Button
    Private progressBar1 As System.Windows.Forms.ProgressBar
    Private resultLabel As System.Windows.Forms.Label
    Private WithEvents backgroundWorker1 As System.ComponentModel.BackgroundWorker


    Public Sub New()
        InitializeComponent()
    End Sub 'New

    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 

    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 'cancelAsyncButton_Click

    ' 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 'backgroundWorker1_DoWork

    ' 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 Not (e.Error Is 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 'backgroundWorker1_RunWorkerCompleted

    ' 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

    ' 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


    Private Sub InitializeComponent()
        Me.numericUpDown1 = New System.Windows.Forms.NumericUpDown
        Me.startAsyncButton = New System.Windows.Forms.Button
        Me.cancelAsyncButton = New System.Windows.Forms.Button
        Me.resultLabel = New System.Windows.Forms.Label
        Me.progressBar1 = New System.Windows.Forms.ProgressBar
        Me.backgroundWorker1 = New System.ComponentModel.BackgroundWorker
        CType(Me.numericUpDown1, System.ComponentModel.ISupportInitialize).BeginInit()
        Me.SuspendLayout()
        '
        'numericUpDown1
        '
        Me.numericUpDown1.Location = New System.Drawing.Point(16, 16)
        Me.numericUpDown1.Maximum = New Decimal(New Integer() {91, 0, 0, 0})
        Me.numericUpDown1.Minimum = New Decimal(New Integer() {1, 0, 0, 0})
        Me.numericUpDown1.Name = "numericUpDown1"
        Me.numericUpDown1.Size = New System.Drawing.Size(80, 20)
        Me.numericUpDown1.TabIndex = 0
        Me.numericUpDown1.Value = New Decimal(New Integer() {1, 0, 0, 0})
        '
        'startAsyncButton
        '
        Me.startAsyncButton.Location = New System.Drawing.Point(16, 72)
        Me.startAsyncButton.Name = "startAsyncButton"
        Me.startAsyncButton.Size = New System.Drawing.Size(120, 23)
        Me.startAsyncButton.TabIndex = 1
        Me.startAsyncButton.Text = "Start Async"
        '
        'cancelAsyncButton
        '
        Me.cancelAsyncButton.Enabled = False
        Me.cancelAsyncButton.Location = New System.Drawing.Point(153, 72)
        Me.cancelAsyncButton.Name = "cancelAsyncButton"
        Me.cancelAsyncButton.Size = New System.Drawing.Size(119, 23)
        Me.cancelAsyncButton.TabIndex = 2
        Me.cancelAsyncButton.Text = "Cancel Async"
        '
        'resultLabel
        '
        Me.resultLabel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D
        Me.resultLabel.Location = New System.Drawing.Point(112, 16)
        Me.resultLabel.Name = "resultLabel"
        Me.resultLabel.Size = New System.Drawing.Size(160, 23)
        Me.resultLabel.TabIndex = 3
        Me.resultLabel.Text = "(no result)"
        Me.resultLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter
        '
        'progressBar1
        '
        Me.progressBar1.Location = New System.Drawing.Point(18, 48)
        Me.progressBar1.Name = "progressBar1"
        Me.progressBar1.Size = New System.Drawing.Size(256, 8)
        Me.progressBar1.TabIndex = 4
        '
        'backgroundWorker1
        '
        Me.backgroundWorker1.WorkerReportsProgress = True
        Me.backgroundWorker1.WorkerSupportsCancellation = True
        '
        'FibonacciForm
        '
        Me.ClientSize = New System.Drawing.Size(292, 118)
        Me.Controls.Add(Me.progressBar1)
        Me.Controls.Add(Me.resultLabel)
        Me.Controls.Add(Me.cancelAsyncButton)
        Me.Controls.Add(Me.startAsyncButton)
        Me.Controls.Add(Me.numericUpDown1)
        Me.Name = "FibonacciForm"
        Me.Text = "Fibonacci Calculator"
        CType(Me.numericUpDown1, System.ComponentModel.ISupportInitialize).EndInit()
        Me.ResumeLayout(False)

    End Sub 'InitializeComponent

    <STAThread()> _
    Shared Sub Main()
        Application.Run(New FibonacciForm)
    End Sub 'Main
End Class 'FibonacciForm 
C#
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;

namespace BackgroundWorkerExample
{    
    public class FibonacciForm : System.Windows.Forms.Form
    {    
        private int numberToCompute = 0;
        private int highestPercentageReached = 0;

        private System.Windows.Forms.NumericUpDown numericUpDown1;
        private System.Windows.Forms.Button startAsyncButton;
        private System.Windows.Forms.Button cancelAsyncButton;
        private System.Windows.Forms.ProgressBar progressBar1;
        private System.Windows.Forms.Label resultLabel;
        private System.ComponentModel.BackgroundWorker backgroundWorker1;

        public FibonacciForm()
        {    
            InitializeComponent();

            InitializeBackgoundWorker();
        }

        // Set up the BackgroundWorker object by 
        // attaching event handlers. 
        private void InitializeBackgoundWorker()
        {
            backgroundWorker1.DoWork += 
                new DoWorkEventHandler(backgroundWorker1_DoWork);
            backgroundWorker1.RunWorkerCompleted += 
                new RunWorkerCompletedEventHandler(
            backgroundWorker1_RunWorkerCompleted);
            backgroundWorker1.ProgressChanged += 
                new ProgressChangedEventHandler(
            backgroundWorker1_ProgressChanged);
        }
    
        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 void cancelAsyncButton_Click(System.Object sender, 
            System.EventArgs e)
        {   
            // Cancel the asynchronous operation.
            this.backgroundWorker1.CancelAsync();

            // Disable the Cancel button.
            cancelAsyncButton.Enabled = false;
        }

        // 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 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 updates the progress bar.
        private void backgroundWorker1_ProgressChanged(object sender,
            ProgressChangedEventArgs e)
        {
            this.progressBar1.Value = e.ProgressPercentage;
        }

        // 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;
        }


        #region Windows Form Designer generated code
        
        private void InitializeComponent()
        {
            this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
            this.startAsyncButton = new System.Windows.Forms.Button();
            this.cancelAsyncButton = new System.Windows.Forms.Button();
            this.resultLabel = new System.Windows.Forms.Label();
            this.progressBar1 = new System.Windows.Forms.ProgressBar();
            this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
            this.SuspendLayout();
            // 
            // numericUpDown1
            // 
            this.numericUpDown1.Location = new System.Drawing.Point(16, 16);
            this.numericUpDown1.Maximum = new System.Decimal(new int[] {
            91,
            0,
            0,
            0});
            this.numericUpDown1.Minimum = new System.Decimal(new int[] {
            1,
            0,
            0,
            0});
            this.numericUpDown1.Name = "numericUpDown1";
            this.numericUpDown1.Size = new System.Drawing.Size(80, 20);
            this.numericUpDown1.TabIndex = 0;
            this.numericUpDown1.Value = new System.Decimal(new int[] {
            1,
            0,
            0,
            0});
            // 
            // startAsyncButton
            // 
            this.startAsyncButton.Location = new System.Drawing.Point(16, 72);
            this.startAsyncButton.Name = "startAsyncButton";
            this.startAsyncButton.Size = new System.Drawing.Size(120, 23);
            this.startAsyncButton.TabIndex = 1;
            this.startAsyncButton.Text = "Start Async";
            this.startAsyncButton.Click += new System.EventHandler(this.startAsyncButton_Click);
            // 
            // cancelAsyncButton
            // 
            this.cancelAsyncButton.Enabled = false;
            this.cancelAsyncButton.Location = new System.Drawing.Point(153, 72);
            this.cancelAsyncButton.Name = "cancelAsyncButton";
            this.cancelAsyncButton.Size = new System.Drawing.Size(119, 23);
            this.cancelAsyncButton.TabIndex = 2;
            this.cancelAsyncButton.Text = "Cancel Async";
            this.cancelAsyncButton.Click += new System.EventHandler(this.cancelAsyncButton_Click);
            // 
            // resultLabel
            // 
            this.resultLabel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
            this.resultLabel.Location = new System.Drawing.Point(112, 16);
            this.resultLabel.Name = "resultLabel";
            this.resultLabel.Size = new System.Drawing.Size(160, 23);
            this.resultLabel.TabIndex = 3;
            this.resultLabel.Text = "(no result)";
            this.resultLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
            // 
            // progressBar1
            // 
            this.progressBar1.Location = new System.Drawing.Point(18, 48);
            this.progressBar1.Name = "progressBar1";
            this.progressBar1.Size = new System.Drawing.Size(256, 8);
            this.progressBar1.Step = 2;
            this.progressBar1.TabIndex = 4;
            // 
            // backgroundWorker1
            // 
            this.backgroundWorker1.WorkerReportsProgress = true;
            this.backgroundWorker1.WorkerSupportsCancellation = true;
            // 
            // FibonacciForm
            // 
            this.ClientSize = new System.Drawing.Size(292, 118);
            this.Controls.Add(this.progressBar1);
            this.Controls.Add(this.resultLabel);
            this.Controls.Add(this.cancelAsyncButton);
            this.Controls.Add(this.startAsyncButton);
            this.Controls.Add(this.numericUpDown1);
            this.Name = "FibonacciForm";
            this.Text = "Fibonacci Calculator";
            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
            this.ResumeLayout(false);

        }
        #endregion

        [STAThread]
        static void Main()
        {
            Application.Run(new FibonacciForm());
        }
    }
}
C++
#using <System.Drawing.dll>
#using <System.dll>
#using <System.Windows.Forms.dll>

using namespace System;
using namespace System::Collections;
using namespace System::ComponentModel;
using namespace System::Drawing;
using namespace System::Threading;
using namespace System::Windows::Forms;

public ref class FibonacciForm: public System::Windows::Forms::Form
{
private:

   int numberToCompute;
   int highestPercentageReached;

   System::Windows::Forms::NumericUpDown^ numericUpDown1;
   System::Windows::Forms::Button^ startAsyncButton;
   System::Windows::Forms::Button^ cancelAsyncButton;
   System::Windows::Forms::ProgressBar^ progressBar1;
   System::Windows::Forms::Label ^ resultLabel;
   System::ComponentModel::BackgroundWorker^ backgroundWorker1;

public:
   FibonacciForm()
   {
      InitializeComponent();
      numberToCompute = highestPercentageReached = 0;
      InitializeBackgoundWorker();
   }


private:

   // Set up the BackgroundWorker object by 
   // attaching event handlers. 
   void InitializeBackgoundWorker()
   {
      backgroundWorker1->DoWork += gcnew DoWorkEventHandler( this, &FibonacciForm::backgroundWorker1_DoWork );
      backgroundWorker1->RunWorkerCompleted += gcnew RunWorkerCompletedEventHandler( this, &FibonacciForm::backgroundWorker1_RunWorkerCompleted );
      backgroundWorker1->ProgressChanged += gcnew ProgressChangedEventHandler( this, &FibonacciForm::backgroundWorker1_ProgressChanged );
   }

   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 );
   }

   void cancelAsyncButton_Click( System::Object^ /*sender*/, System::EventArgs^ /*e*/ )
   {  
      // Cancel the asynchronous operation.
      this->backgroundWorker1->CancelAsync();
      
      // Disable the Cancel button.
      cancelAsyncButton->Enabled = false;
   }

   // 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 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 updates the progress bar.
   void backgroundWorker1_ProgressChanged( Object^ /*sender*/, ProgressChangedEventArgs^ e )
   {
      this->progressBar1->Value = e->ProgressPercentage;
   }

   // 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;
   }

   void InitializeComponent()
   {
      this->numericUpDown1 = gcnew System::Windows::Forms::NumericUpDown;
      this->startAsyncButton = gcnew System::Windows::Forms::Button;
      this->cancelAsyncButton = gcnew System::Windows::Forms::Button;
      this->resultLabel = gcnew System::Windows::Forms::Label;
      this->progressBar1 = gcnew System::Windows::Forms::ProgressBar;
      this->backgroundWorker1 = gcnew System::ComponentModel::BackgroundWorker;
      (dynamic_cast<System::ComponentModel::ISupportInitialize^>(this->numericUpDown1))->BeginInit();
      this->SuspendLayout();
      
      // 
      // numericUpDown1
      // 
      this->numericUpDown1->Location = System::Drawing::Point( 16, 16 );
      array<Int32>^temp0 = {91,0,0,0};
      this->numericUpDown1->Maximum = System::Decimal( temp0 );
      array<Int32>^temp1 = {1,0,0,0};
      this->numericUpDown1->Minimum = System::Decimal( temp1 );
      this->numericUpDown1->Name = "numericUpDown1";
      this->numericUpDown1->Size = System::Drawing::Size( 80, 20 );
      this->numericUpDown1->TabIndex = 0;
      array<Int32>^temp2 = {1,0,0,0};
      this->numericUpDown1->Value = System::Decimal( temp2 );

      // 
      // startAsyncButton
      // 
      this->startAsyncButton->Location = System::Drawing::Point( 16, 72 );
      this->startAsyncButton->Name = "startAsyncButton";
      this->startAsyncButton->Size = System::Drawing::Size( 120, 23 );
      this->startAsyncButton->TabIndex = 1;
      this->startAsyncButton->Text = "Start Async";
      this->startAsyncButton->Click += gcnew System::EventHandler( this, &FibonacciForm::startAsyncButton_Click );

      // 
      // cancelAsyncButton
      // 
      this->cancelAsyncButton->Enabled = false;
      this->cancelAsyncButton->Location = System::Drawing::Point( 153, 72 );
      this->cancelAsyncButton->Name = "cancelAsyncButton";
      this->cancelAsyncButton->Size = System::Drawing::Size( 119, 23 );
      this->cancelAsyncButton->TabIndex = 2;
      this->cancelAsyncButton->Text = "Cancel Async";
      this->cancelAsyncButton->Click += gcnew System::EventHandler( this, &FibonacciForm::cancelAsyncButton_Click );

      // 
      // resultLabel
      // 
      this->resultLabel->BorderStyle = System::Windows::Forms::BorderStyle::Fixed3D;
      this->resultLabel->Location = System::Drawing::Point( 112, 16 );
      this->resultLabel->Name = "resultLabel";
      this->resultLabel->Size = System::Drawing::Size( 160, 23 );
      this->resultLabel->TabIndex = 3;
      this->resultLabel->Text = "(no result)";
      this->resultLabel->TextAlign = System::Drawing::ContentAlignment::MiddleCenter;

      // 
      // progressBar1
      // 
      this->progressBar1->Location = System::Drawing::Point( 18, 48 );
      this->progressBar1->Name = "progressBar1";
      this->progressBar1->Size = System::Drawing::Size( 256, 8 );
      this->progressBar1->Step = 2;
      this->progressBar1->TabIndex = 4;

      // 
      // backgroundWorker1
      // 
      this->backgroundWorker1->WorkerReportsProgress = true;
      this->backgroundWorker1->WorkerSupportsCancellation = true;

      // 
      // FibonacciForm
      // 
      this->ClientSize = System::Drawing::Size( 292, 118 );
      this->Controls->Add( this->progressBar1 );
      this->Controls->Add( this->resultLabel );
      this->Controls->Add( this->cancelAsyncButton );
      this->Controls->Add( this->startAsyncButton );
      this->Controls->Add( this->numericUpDown1 );
      this->Name = "FibonacciForm";
      this->Text = "Fibonacci Calculator";
      (dynamic_cast<System::ComponentModel::ISupportInitialize^>(this->numericUpDown1))->EndInit();
      this->ResumeLayout( false );
   }
};

[STAThread]
int main()
{
   Application::Run( gcnew FibonacciForm );
}
J#
import System.* ;
import System.Collections.* ;
import System.ComponentModel.* ;
import System.Drawing.* ;
import System.Threading.* ;
import System.Windows.Forms.* ;

public class FibonacciForm extends System.Windows.Forms.Form
{
    private int numberToCompute = 0;
    private int highestPercentageReached = 0;

    private System.Windows.Forms.NumericUpDown numericUpDown1;
    private System.Windows.Forms.Button startAsyncButton;
    private System.Windows.Forms.Button cancelAsyncButton;
    private System.Windows.Forms.ProgressBar progressBar1;
    private System.Windows.Forms.Label resultLabel;
    private System.ComponentModel.BackgroundWorker backgroundWorker1;

    public FibonacciForm()
    {
        InitializeComponent();
        InitializeBackgoundWorker();
    } //FibonacciForm

    // Set up the BackgroundWorker object by 
    // attaching event handlers. 
    private void InitializeBackgoundWorker()
    {
        backgroundWorker1.add_DoWork(new DoWorkEventHandler(
            backgroundWorker1_DoWork));
        backgroundWorker1.add_RunWorkerCompleted(
            new RunWorkerCompletedEventHandler(
            backgroundWorker1_RunWorkerCompleted));
        backgroundWorker1.add_ProgressChanged(
            new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged));
    } //InitializeBackgoundWorker

    private void startAsyncButton_Click(Object sender, EventArgs e)
    {
        // Reset the text in the result label.
        resultLabel.set_Text(String.Empty);

        // Disable the UpDown control until 
        // the asynchronous operation is done.
        this.numericUpDown1.set_Enabled(false);

        // Disable the Start button until 
        // the asynchronous operation is done.
        this.startAsyncButton.set_Enabled(false);

        // Enable the Cancel button while 
        // the asynchronous operation runs.
        this.cancelAsyncButton.set_Enabled(true);

        // Get the value from the UpDown control.
        numberToCompute = System.Convert.ToInt32((numericUpDown1.get_Value()));

        // Reset the variable for percentage tracking.
        highestPercentageReached = 0;

        // Start the asynchronous operation.
        backgroundWorker1.RunWorkerAsync(System.Convert.ToString
            (numberToCompute));
    }
    
    private void cancelAsyncButton_Click(Object sender, System.EventArgs e)
    {   
        // Cancel the asynchronous operation.
        this.backgroundWorker1.CancelAsync();

        // Disable the Cancel button.
        cancelAsyncButton.set_Enabled(false);
    }


    // 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 = (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.set_Result(new Long(ComputeFibonacci(System.Convert.ToInt32
            (e.get_Argument()), worker, e)));
        //e.Result = ComputeFibonacci((int)e.Argument, worker, e); 
    } //backgroundWorker1_DoWork

    // 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.get_Error() != null) {
        
            MessageBox.Show(e.get_Error().get_Message());
        }
        else {
        
            if (e.get_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.set_Text("Cancelled");
            }
            else {
            
                // Finally, handle the case where the operation 
                // succeeded.
                resultLabel.set_Text(e.get_Result().ToString());
            }
        }

        // Enable the UpDown control.
        this.numericUpDown1.set_Enabled(true);

        // Enable the Start button.
        startAsyncButton.set_Enabled(true);

        // Disable the Cancel button.
        cancelAsyncButton.set_Enabled(false);
    } //backgroundWorker1_RunWorkerCompleted

    // This event handler updates the progress bar.
    private void backgroundWorker1_ProgressChanged(Object sender,
        ProgressChangedEventArgs e)
    {
        this.progressBar1.set_Value(e.get_ProgressPercentage());
    } //backgroundWorker1_ProgressChanged

    // 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 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.get_CancellationPending()) {
        
            e.set_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;
    } 

    #region Windows Form Designer generated code
    private void InitializeComponent()
    {
        this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
        this.startAsyncButton = new System.Windows.Forms.Button();
        this.cancelAsyncButton = new System.Windows.Forms.Button();
        this.resultLabel = new System.Windows.Forms.Label();
        this.progressBar1 = new System.Windows.Forms.ProgressBar();
        this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
        ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).
            BeginInit();
        this.SuspendLayout();

        // 
        // numericUpDown1
        // 
        this.numericUpDown1.set_Location(new System.Drawing.Point(16, 16));
        this.numericUpDown1.set_Maximum(new System.Decimal(
            new int[] { 91, 0, 0, 0 }));
        this.numericUpDown1.set_Minimum(new System.Decimal(
            new int[] { 1, 0, 0, 0 }));
        this.numericUpDown1.set_Name("numericUpDown1");
        this.numericUpDown1.set_Size(new System.Drawing.Size(80, 20));
        this.numericUpDown1.set_TabIndex(0);
        this.numericUpDown1.set_Value(new System.Decimal(
            new int[] { 1, 0, 0, 0 }));

        // 
        // startAsyncButton
        // 
        this.startAsyncButton.set_Location(new System.Drawing.Point(16, 72));
        this.startAsyncButton.set_Name("startAsyncButton");
        this.startAsyncButton.set_Size(new System.Drawing.Size(120, 23));
        this.startAsyncButton.set_TabIndex(1);
        this.startAsyncButton.set_Text("Start Async");
        this.startAsyncButton.add_Click(
            new System.EventHandler(this.startAsyncButton_Click));

        // 
        // cancelAsyncButton
        // 
        this.cancelAsyncButton.set_Enabled(false);
        this.cancelAsyncButton.set_Location(new System.Drawing.Point(153, 72));
        this.cancelAsyncButton.set_Name("cancelAsyncButton");
        this.cancelAsyncButton.set_Size(new System.Drawing.Size(119, 23));
        this.cancelAsyncButton.set_TabIndex(2);
        this.cancelAsyncButton.set_Text("Cancel Async");
        this.cancelAsyncButton.add_Click(
            new System.EventHandler(this.cancelAsyncButton_Click));

        // 
        // resultLabel
        // 
        this.resultLabel.set_BorderStyle(System.Windows.Forms.BorderStyle.Fixed3D);
        this.resultLabel.set_Location(new System.Drawing.Point(112, 16));
        this.resultLabel.set_Name("resultLabel");
        this.resultLabel.set_Size(new System.Drawing.Size(160, 23));
        this.resultLabel.set_TabIndex(3);
        this.resultLabel.set_Text("(no result)");
        this.resultLabel.set_TextAlign(System.Drawing.ContentAlignment.MiddleCenter);

        // 
        // progressBar1
        // 
        this.progressBar1.set_Location(new System.Drawing.Point(18, 48));
        this.progressBar1.set_Name("progressBar1");
        this.progressBar1.set_Size(new System.Drawing.Size(256, 8));
        this.progressBar1.set_Step(2);
        this.progressBar1.set_TabIndex(4);

        // 
        // backgroundWorker1
        // 
        this.backgroundWorker1.set_WorkerReportsProgress(true);
        this.backgroundWorker1.set_WorkerSupportsCancellation(true);

        // 
        // FibonacciForm
        // 
        this.set_ClientSize(new System.Drawing.Size(292, 118));
        this.get_Controls().Add(this.progressBar1);
        this.get_Controls().Add(this.resultLabel);
        this.get_Controls().Add(this.cancelAsyncButton);
        this.get_Controls().Add(this.startAsyncButton);
        this.get_Controls().Add(this.numericUpDown1);
        this.set_Name("FibonacciForm");
        this.set_Text("Fibonacci Calculator");
        ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).
            EndInit();
        this.ResumeLayout(false);
    } //InitializeComponent
    #endregion

    /** @attribute STAThread()
     */
    public static void main(String[] args)
    {
        Application.Run(new FibonacciForm());
    } //main
} //FibonacciForm
   

编译代码

  • 若要编译此示例,必须导入 System.ComponentModel 命名空间并引用 System.Design 程序集。

可靠编程

Caution note警告

使用任何一种多线程都可能引起极为严重和复杂的 bug。在实现使用多线程的任何解决方案之前,请参考托管线程处理的最佳做法

分享到:
评论

相关推荐

    C#中使用BackgroundWorker 实现后台操作窗体

    C#,使用,BackgroundWorker ,实现,后台操作窗体 C#,使用,BackgroundWorker ,实现,后台操作窗体 C#,使用,BackgroundWorker ,实现,后台操作窗体 C#,使用,BackgroundWorker ,实现,后台操作窗体 C#,使用...

    Prism MVVM应用 登陆后切换主窗体实现

    登陆窗体(以下简称 LoginView)和程序布局主窗体(以下简称 MainView),分别利用IRegionManager进行管理,根据需要在不同时机相继出场表演。所有操作均由各自ViewModel(简称VM)代码完成。  1.当程序启动后,...

    C#四种方式实现对用户操作响应灵敏及可动态更新的窗体控件及其对比

    1.4种方式都可以实现要求 可谓条条大路通罗马 2.多线程和委托需要强行禁用CheckForIllegalCrossThreadCalls,有可能存在运行安全问题,但目前还没遇到 3.timer的源代码最少最简单 其次是多线程 4.委托本质上还是...

    毕业设计-基于SpringBoot后台管理系统,使用layui

    项目实现基础的后台权限功能: 用户管理 角色管理 菜单管理 按钮管理 用户角色关联管理 角色菜单关联管理 角色菜单按钮关联管理 系统综合: 操作日志管理:记录用户登录日志信息 类型管理:用于系统内部动态类型不用...

    《windows mobile 手机应用开发》源码

    后台服务程序的使用范例(使用MFC) AppletDemo:创建控制面板程序范例 StorageCardDemo:CStorageCard类使用范例 &lt;br&gt;第4章 ContextMenuText:上下文菜单的实现。 Multiviews:多视图窗口切换的...

    CLR.via.C#.(中文第3版)(自制详细书签)Part2

    · 使用线程池、任务、取消、计时器和异步I/O操作来设计响应性强、稳定性高和伸缩性大的解决方案 · 借助于异常处理来进行状态管理 · 使用CLR寄宿、AppDomain、程序集加载、反射和C#的dynamic类型来构造具有动态...

    JavaSpring Boot框架开发的报名系统.zip

    在实现以上前端设计以后,开始后台设计,后台主要以WinForm窗体的形式来展现给用户,它的对象,主要是各个院校,机构的招生部门,权限是管理员。用户下载这个客户端,并且有自己的管理员账号,登录成功后,可在主...

    多线程操作窗口源码

    多数时候,我们的操作模式是后台 线程中处理数据,计算结果,然后在前台界面(GUI) 中更新显示。 在.NET Framework中,为了保证线程安全,避免出 现访问竞争等问题,是不允许跨线程访问窗体控件的。 如果强行访问...

    WinForm进度条的2种异步实现方式

    CancellationPending——指示应用程序是否已请求取消后台操作。 IsBusy——指示 BackgroundWorker 是否正在运行异步操作 WorkerReportsProgress——该值指示 BackgroundWorker 能否报告进度更新 ...

    学生信息管理系统

    前台窗体的展现要靠在数据库中建立窗体来实现,要求能够保护数据库的安全,提示用户如何更好地使用该系统等多项功能。学生信息管理系统的总目标是对学生信息进行存储、查询、修改和删除等操作。

    多线程操作窗口源码2012813

    多数时候,我们的操作模式是后台 线程中处理数据,计算结果,然后在前台界面(GUI) 中更新显示。 在.NET Framework中,为了保证线程安全,避免出 现访问竞争等问题,是不允许跨线程访问窗体控件的。 如果强行访问...

    数据库课程设计报告-人事管理系统.doc

    1)良好的人机界面 2)要求实现一定的权限管理 3)方便的数据查询功能 4)方便的添加,删除和修改数据功能 二:开发工具选择 本系统采用SQL Server 2005创建后台数据库,前台开发工具利用Visual Studio 2005进行...

    学生成绩管理系统的设计与实现

    实现了数据库表的浏览,记录的添加、删除和修改,报表的生成,实现了多数据库表的连接操作,实现了多条件查询和模糊查询,并灵活实现了对不可更新查询结果集的更新操作,实现了主从表操作,实现了密码维护功能,最后...

    毕业设计依据vb学生档案管理系统设计与实现

    学生档案管理系统是典型的信息管理系统(MIS),其开发主要包括后台数据库的建立和维护...这三种操作均可由Visual Basic 创建的程序来完成,下面的章节将详细描述实现的具体方法。打开记录操作进入记录操作选项页分别由浏

    java实习报告(5).doc

    Windows XP 编程环境:MyEclipse 6.0 主要技术:Java Swing实现窗体界面 JDBC实现数据库操作 系统架构:三层架构(MVC)+DAO设计模式 数据库:MySQL5.0 二:课设内容; 1)系统功能需求 学生信息管理系统主要对在校学生...

    C# 模拟浏览器并自动操作的实例代码

    本文主要讲解通过WebBrowser控件打开浏览页面,并操作页面元素实现自动搜索功能,仅供学习分享使用,如有不足之处,还请指正。 涉及知识点 WebBrowser:用于在WinForm窗体中,模拟浏览器,打开并导航网页。 ...

    easyui+增强窗体 demo_ext为实例文件

    1、$.showWindow 和 $.showModalDialog 在useiframe=true时,对窗体body增加遮罩控制。 2、easyui.tabs的add方法当useiframe=true时,增加遮罩控制。 3、toolbar增加url属性,可以通过请求后台数据构建。 4、增加...

    一个基于C#技术实现的命令行工具源程序代码

    一个基于C#技术实现的命令行工具源程序代码,该工具采用C#+VS2005开发实现,可以通过命令方式实现对后台执行程序代码的动作解析操作。

    图书馆管理系统课程设计报告.doc.doc

    2)结构设计: 根据上面的需求分析,开发设计不同的窗体系统,每一个窗体实现不同 的功能,可以设计下面的几个模块。 图书管理模块:用来实现图书类别和信息管理。 读者管理模块:用来实现读者类别和信息管理。 图书...

    JAVA项目开发全程实录(含电子书和所有源代码)

    4.11.3 后台管理工作区实现过程 181 4.11.4 单元测试 188 4.12 开发技巧与难点分析 188 4.13 使用Visio逆向生成数据库E-R图 190 4.14 本章总结 192 第5章 图书馆管理系统(Swing+SQL Server 2000实现) 193 教学...

Global site tag (gtag.js) - Google Analytics