C#笔记(异步编程2-后台线程与任务并行库)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_38801354/article/details/79788601

1 BackgroundWorker

aysnc/await 特性适合那些需要在后台完成的不相关的小任务,但有时候,可能需要另建一个线程,在后台持续运行以完成某项工作,并时不时地与主线程进行通信。而 BackgroundWorker 类就是为此而生。
BackgroundWorker 类有几个主要的成员:

  • 属性:
    • WorkerReportProgress:布尔值,可写可读,用于表示是否支持向主线程汇报它的进度;
    • WorkerSupportsCancellation:布尔值,可写可读,用于表示是否支持从主线程取消;
    • IsBusy:只读布尔值,检查后台任务是否在运行;
    • CancellationPending:只读布尔值,由 CancellAsnyc 方法控制,DoWork 事件程序需要检查其属性来决定是否应该停止处理;
  • 方法:用于初始化行为或改变状态
    • RunWorkerAsync():调用 RunWorkerAsync() 方法可以获取后台线程并执行 DoWork 事件处理程序;
    • CancellAsnyc():用于改变 CancellationPending 属性为 trueDoWork 事件程序必须检查其属性值来决定是否停止处理;
    • ReportProgress():向主线程汇报进度,主线程可以处理 ProgressChanged 事件上的处理程序;
  • 事件:
    • DoWork:后台线程开始的时候触发 DoWork 事件(创建 BackgroundWorker 类必需);
    • ProgressChanged:在后台任务汇报状态的时候触发 ProgressChanged 事件;
    • RunWorkerComplated:在后台任务结束的时候触发 RunWorkerComplated 事件;

事件处理程序都有一个 object 对象的引用作为 第一个参数,以及 EventArgs 类的特定子类作为 第二个参数,对应的 EventArgs 类依次分别是:

  • DoWorkEventArgs
    • Argument
    • Result
    • Cancel
  • ProgressChangedEventArgs
    • ProgressPercentage
    • UserState
  • RunWorkerCompletedEventArgs
    • Cancelled
    • Error
    • Result
    • UserState

示例代码:

using System.Windows;
using System.ComponentModel;
sing System.Threading;

namespace SimpleWorker
{
    public partial class MainWindow:Window
    {
        // 初始化 BackgroundWorker
        BackgroundWorker bgWorker = new BackgroundWorker();

        public MainWindow()
        {
            InitializeCompoonent();

            // 设置 BackgroundWorker 属性
            bgWorker.WorkerReportsProgress = true;
            bgWorker.WorkerSupportsCancellation = true;

            // 链接BackgroundWorker对象的处理程序
            bgWorker.DoWork += DoWork_Handler;
            bgWorker.ProgressChanged += ProgressChanged_Handler;
            bgWorker.RunWorkerCompleted += RunWorkerCompleted_Handler;
        }

        private void btnProcess_Click(object sender, RoutedEventArgs e)
        {
            progressBar.Value = args.ProgressPercentage;
        }
        private void DoWork_Handler(object sender, DoWorkerEeventArgs args)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            for (int i=1; i<=10; i++)
            {
                if (worker.CancellationPending)
                {
                    args.Cancel = true;
                    break;  
                }
                else
                {
                    worker.ReportProgress(i*10);
                    Thread.Sleep(500);
                }
            }
        }
        private void RunWorkerCompleted_Handler(object sender, RunWorkerCompletedEventArgs args)
        {
            progressBar.Value = 0;
            if (args.Cancelled)
            {
                MessageBox.Show("Process was cancelled.", "Process Cancelled");
            }
            else
            {
                MessageBox.Show("Process completed normally.", "Process Completed");
            }
        }
        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            bgWorker.CancelAsync();
        }
    }
}

2 任务并行库

任务并行库(Task Parellel Library),它是BCL的一个类库,极大简化了并行编程。

2.1 并行循环

Parallel.For 循环和 Parallel.ForEach 循环位于 System.Threading.Tasks 命名空间中,使用它们可以使得彼此独立的迭代程序运行再不同的处理器上 并行 处理。
Parallel.For 循环有 12 个重载,最简单的示例:

using System;
using System.Threading.Tasks;

namespace ExampleParallelFor
{
    class Program
    {
        static void Main()
        {
            Parallel.For(0, 15, i => {
                Console.WriteLine("The square of {0} is {1}", i, i*i); // 此时输出的次序不能保证
            })
        }
    }
}

同理使用 Parallel.ForEach 最简单重载的示例

using System;
using System.Threading.Tasks;

namespace ParallelForeach1
{
    static void Main()
    {
        string[] squares = new string[] {"Hello", "World", "!"};
        Parallel.ForEach(squares, i => {
            Console.WriteLine(string.Format("{o} has {1} letters", i, i.Length));
        })
    }
}

猜你喜欢

转载自blog.csdn.net/qq_38801354/article/details/79788601