• .NET : 再谈谈多线程


    这几天在讲.NET核心编程时再次探讨到了多线程这一部分。其中,我们讨论到如果使用BackgroundWorker这个组件的话,那么它的几个事件到底是运行在几个线程的。下面是一个例子

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ComponentModel;
    using System.Threading;

    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                BackgroundWorker worker = new BackgroundWorker();
                worker.DoWork += new DoWorkEventHandler(worker_DoWork);
                worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
                worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
                worker.WorkerReportsProgress = true;

                Console.WriteLine("主方法运行的线程:{0}", Thread.CurrentThread.ManagedThreadId);

                worker.RunWorkerAsync();

                Console.Read();
            }

            static void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                Console.WriteLine("进度更新方法运行的线程:{0}", Thread.CurrentThread.ManagedThreadId);

            }

            static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                Console.WriteLine("异步方法完成,运行的线程:{0}", Thread.CurrentThread.ManagedThreadId);
            }

            static void worker_DoWork(object sender, DoWorkEventArgs e)
            {
                Console.WriteLine("执行异步方法,线程:{0}", Thread.CurrentThread.ManagedThreadId);
                BackgroundWorker worker = (BackgroundWorker)sender;
                worker.ReportProgress(10);
            }
        }
    }

     

    答案是:有时候是这样

    image 

    有时候又这样(我在Do_Work事件里面加了一个Sleep之后的效果)

    image

    这的确有点让人捉摸不透。这意味着什么呢?我想,这意味着,只有一点是可以确认的:主方法运行在一个线程,而要后台操作的方法运行在另外一个线程,至于这个后台方法的进度汇报或者完成事件,则可能与后台方法在一个线程,也可能不在一个线程。这估计是取决于后台方法本身所消耗的时间,以及运行环境的线程利用情况而定。

    以上行为在Windows Forms的原理却不是一样的

    using System;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Threading;

    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();

                BackgroundWorker worker = new BackgroundWorker();
                worker.DoWork += new DoWorkEventHandler(worker_DoWork);
                worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
                worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
                worker.WorkerReportsProgress = true;

                Console.WriteLine("主方法运行的线程:{0}", Thread.CurrentThread.ManagedThreadId);

                worker.RunWorkerAsync();

            }

            static void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                Console.WriteLine("进度更新方法运行的线程:{0}", Thread.CurrentThread.ManagedThreadId);

            }

            static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                Console.WriteLine("异步方法完成,运行的线程:{0}", Thread.CurrentThread.ManagedThreadId);
            }

            static void worker_DoWork(object sender, DoWorkEventArgs e)
            {
                Console.WriteLine("执行异步方法,线程:{0}", Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(5000);
                BackgroundWorker worker = (BackgroundWorker)sender;
                worker.ReportProgress(10);
            }
        }
    }

    主方法运行的线程:8
    执行异步方法,线程:9
    进度更新方法运行的线程:8
    异步方法完成,运行的线程:8

    这是显然有必要的,因为异步方法进度更新或者完成的话,通常我们都需要更新窗体的元素(例如控件),如果此时的线程不是一样的话,就会导致线程安全问题。

     

    最后,总结一下BackgroundWorker这个组件的工作原理

    RunWorkerAsync方法==》触发DoWork事件==》执行DoWork方法(运行在一个独立的线程)==》可以通过调用ReportProgress汇报进度==》触发ProgressChanged事件==》执行ProgressChanged方法==》如果DoWork方法完成了所有操作,则触发RunWorkerCompleted事件==》执行RunWorkerCompleted方法

    本文由作者:陈希章 于 2009/7/21 5:55:22 发布在:http://www.cnblogs.com/chenxizhang/
    本文版权归作者所有,可以转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    更多博客文章,以及作者对于博客引用方面的完整声明以及合作方面的政策,请参考以下站点:陈希章的博客中心
  • 相关阅读:
    谁说AI看不懂视频?
    为什么说容器的崛起预示着云原生时代到来?
    小熊派开发实践丨漫谈LiteOS之传感器移植
    华为云如何赋能无人车飞驰?从这群AI热血少年谈起
    趣味科普丨一文读懂云服务器的那些事儿
    【API进阶之路】研发需求突增3倍,测试团队集体闹离职
    这个应用魔方厉害了,让软件开发者效率提升10倍
    数据安全无小事:揭秘华为云GaussDB(openGauss)全密态数据库
    数据湖探索DLI新功能:基于openLooKeng的交互式分析
    基本数据类型与表达式5 零基础入门学习Delphi06
  • 原文地址:https://www.cnblogs.com/chenxizhang/p/1527440.html
Copyright © 2020-2023  润新知