.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("執(zhí)行異步方法,線程:{0}", Thread.CurrentThread.ManagedThreadId);
??????????? BackgroundWorker worker = (BackgroundWorker)sender;
??????????? worker.ReportProgress(10);
??????? }
??? }
}
?
答案是:有時候是這樣
?
有時候又這樣(我在Do_Work事件里面加了一個Sleep之后的效果)
這的確有點讓人捉摸不透。這意味著什么呢?我想,這意味著,只有一點是可以確認的:主方法運行在一個線程,而要后臺操作的方法運行在另外一個線程,至于這個后臺方法的進度匯報或者完成事件,則可能與后臺方法在一個線程,也可能不在一個線程。這估計是取決于后臺方法本身所消耗的時間,以及運行環(huán)境的線程利用情況而定。
以上行為在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("執(zhí)行異步方法,線程:{0}", Thread.CurrentThread.ManagedThreadId);
??????????? Thread.Sleep(5000);
??????????? BackgroundWorker worker = (BackgroundWorker)sender;
??????????? worker.ReportProgress(10);
??????? }
??? }
}
主方法運行的線程:8
執(zhí)行異步方法,線程:9
進度更新方法運行的線程:8
異步方法完成,運行的線程:8
這是顯然有必要的,因為異步方法進度更新或者完成的話,通常我們都需要更新窗體的元素(例如控件),如果此時的線程不是一樣的話,就會導(dǎo)致線程安全問題。
?
最后,總結(jié)一下BackgroundWorker這個組件的工作原理
RunWorkerAsync方法==》觸發(fā)DoWork事件==》執(zhí)行DoWork方法(運行在一個獨立的線程)==》可以通過調(diào)用ReportProgress匯報進度==》觸發(fā)ProgressChanged事件==》執(zhí)行ProgressChanged方法==》如果DoWork方法完成了所有操作,則觸發(fā)RunWorkerCompleted事件==》執(zhí)行RunWorkerCompleted方法
本文由作者:陳希章 于 2009/7/21 5:55:22 發(fā)布在:http://www.cnblogs.com/chenxizhang/本文版權(quán)歸作者所有,可以轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。
更多博客文章,以及作者對于博客引用方面的完整聲明以及合作方面的政策,請參考以下站點:陳希章的博客中心
轉(zhuǎn)載于:https://www.cnblogs.com/chenxizhang/archive/2009/07/21/1527440.html
總結(jié)
以上是生活随笔為你收集整理的.NET : 再谈谈多线程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 奇怪-正则匹配的test函数
- 下一篇: Discuz7使用syntaxhighl