日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

多线程总结之旅(12):跨线程调用控件的几种方式

發(fā)布時(shí)間:2024/1/17 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多线程总结之旅(12):跨线程调用控件的几种方式 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

  本來是寫完線程池就結(jié)束多線程總結(jié)之旅系列的,但是想想平時(shí)在項(xiàng)目中用到線程僅僅不夠的,為什么這么說呢?舉個(gè)例子:我們有一個(gè)函數(shù),它的功能就是加載數(shù)據(jù),然后綁定到datagridview。現(xiàn)在我們開啟一個(gè)線程去執(zhí)行這個(gè)函數(shù)。結(jié)果可想而知,它會(huì)報(bào)錯(cuò):提示線程無(wú)法訪問。。。之類的話。為什么報(bào)錯(cuò)呢?因?yàn)槟阍陂_啟的線程中操作了datagridview控件,也就是你跨線程調(diào)用控件了。 ?

  那么我們應(yīng)該怎么跨線程調(diào)用控件呢?下面我就把我總結(jié)的幾種方法奉獻(xiàn)給各位。

  跨線程調(diào)用控件的幾種方法:

  1、方法一:Control.CheckForIllegalCrossThreadCalls?= false;這是通過禁止編譯器檢查對(duì)跨線程訪問操作,但是這種方法不是安全的解決辦法,盡量不要使用。

  為什么說不安全呢?

    (1)我們查看CheckForIllegalCrossThreadCalls 這個(gè)屬性的定義,就會(huì)發(fā)現(xiàn)它是一個(gè)static的,也就是說無(wú)論我們?cè)陧?xiàng)目的什么地方修改了這個(gè)值,他就會(huì)在全局起作用。

    (2)一般對(duì)于跨線程訪問是否存在異常,我們通常都會(huì)去檢查。如果項(xiàng)目中其他人修改了這個(gè)屬性,那么我們的方案就失敗了。

    代碼下載:http://files.cnblogs.com/files/qtiger/CheckForIllegalCrossThreadCalls.rar

  2、方法二: 使用Delegate和Invoke跨線程調(diào)用控件(也叫代理方式)

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms;namespace WindowsFormsApplication1 {public partial class Form1 : Form{public Form1(){InitializeComponent(); }private void button1_Click(object sender, EventArgs e){Thread t = new Thread(ModifyLabelText);t.Start();}/// <summary>/// 定義委托/// </summary>private delegate void InvokeDelegate();/// <summary>/// this.label1.InvokeRequired就是問問我們要不要使用代理執(zhí)行ModifyLabelText方法/// </summary>private void ModifyLabelText(){//使用Invoke代理的方式調(diào)用ModifyLabelText方法if (this.label1.InvokeRequired){InvokeDelegate invokeDelegate=new InvokeDelegate(ModifyLabelText);this.Invoke(invokeDelegate); }else{this.label1.Text = "我已經(jīng)跨線程修改了Label的值";}}} }

  代碼下載:http://files.cnblogs.com/files/qtiger/InvokeAndDelegate.zip

  3、方法三:使用BeginInvoke和Delegate的方式。(也叫代理方式)

  

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms;namespace WindowsFormsApplication1 {public partial class Form1 : Form{public Form1(){InitializeComponent(); }private void button1_Click(object sender, EventArgs e){Thread t = new Thread(ModifyLabelText);t.Start();}/// <summary>/// 定義委托/// </summary>private delegate void InvokeDelegate();/// <summary>/// this.label1.InvokeRequired就是問問我們要不要使用代理執(zhí)行ModifyLabelText方法/// </summary>private void ModifyLabelText(){//使用BeginInvoke代理的方式調(diào)用ModifyLabelText方法if (this.label1.InvokeRequired){InvokeDelegate invokeDelegate=new InvokeDelegate(ModifyLabelText);this.BeginInvoke(invokeDelegate); }else{this.label1.Text = "我已經(jīng)跨線程修改了Label的值";}}} }

  在這里進(jìn)行一下說明:Invoke方法和BeginInvoke方法的區(qū)別是Invoke方法是同步的, 它會(huì)等待工作線程完成;BeginInvoke方法是異步的, 它會(huì)另起一個(gè)線程去完成工作線程。

  代碼下載:http://files.cnblogs.com/files/qtiger/BeginInvokeAndDelegate.zip

  4、方法四:使用BackgroundWorker組件(推薦使用這個(gè)方法)

  ?(1)概述BackgroundWorker是·net里用來執(zhí)行多線程任務(wù)的控件,它允許編程者在一個(gè)單獨(dú)的線程上執(zhí)行一些操作。耗時(shí)的操作(如下載和數(shù)據(jù)庫(kù)事務(wù))在長(zhǎng)時(shí)間運(yùn)行時(shí)可能會(huì)導(dǎo)致用戶界面 (UI) 始終處于停止響應(yīng)狀態(tài)。如果您需要能進(jìn)行響應(yīng)的用戶界面,而且面臨與這類操作相關(guān)的長(zhǎng)時(shí)間延遲,則可以使用BackgroundWorker類方便地解決問題。

  (2)工作原理該控件有三個(gè)事件:DoWork 、ProgressChanged 和 RunWorkerCompleted。在程序中調(diào)用RunWorkerAsync方法則會(huì)啟動(dòng)DoWork事件的事件處理,當(dāng)在事件處理過程中,調(diào)用 ReportProgress方法則會(huì)啟動(dòng)ProgressChanged事件的事件處理,而當(dāng)DoWork事件處理完成時(shí),則會(huì)觸發(fā)RunWorkerCompleted事件。

您必須非常小心,確保在 DoWork 事件處理程序中不操作任何用戶界面對(duì)象(否則仍會(huì)停止響應(yīng))。而應(yīng)該通過 ProgressChanged和 RunWorkerCompleted 事件與用戶界面進(jìn)行通信。

?

  

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms;namespace WorkerBackgrounderExmple {public partial class Form1 : Form{public Form1(){InitializeComponent();}private static int MaxRecords = 100;private void btnStart_Click(object sender, EventArgs e){if (backgroundWorker1.IsBusy){return;}this.listView1.Items.Clear();this.backgroundWorker1.RunWorkerAsync(MaxRecords);this.btnStart.Enabled= false;this.btnCancel.Enabled= true;}private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e){try{e.Result = this.RetrieveData(this.backgroundWorker1, e);}catch (Exception ex){MessageBox.Show(ex.Message);throw;}}private int RetrieveData(BackgroundWorker worker, DoWorkEventArgs e){int maxRecords=(int)e.Argument;int percent=0;for (int i = 1; i <=maxRecords; i++){if (worker.CancellationPending){return i;}percent=(int)(((double)i/(double)maxRecords)*100);worker.ReportProgress(percent, new KeyValuePair<int, string>(i, Guid.NewGuid().ToString()));Thread.Sleep(100);}return maxRecords;}private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e){KeyValuePair<int, string> record = (KeyValuePair<int, string>)e.UserState;this.label1.Text = string.Format("There are {0} records retrieved!", record.Key);this.progressBar1.Value = e.ProgressPercentage;this.listView1.Items.Add(record.Value);}private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e){try{this.label1.Text = string.Format("Total records: {0}", e.Result);this.btnStart.Enabled = true;this.btnCancel.Enabled = false;}catch (TargetInvocationException ex){MessageBox.Show(ex.InnerException.GetType().ToString());}}private void btnCancel_Click(object sender, EventArgs e){this.backgroundWorker1.CancelAsync();}} }

?

  源碼下載:http://files.cnblogs.com/files/qtiger/WorkerBackgrounderExmple.zip

?

?

?

?

  多線程這一塊就總結(jié)到這了,都是平時(shí)自己總結(jié)的東西,希望對(duì)大家有用,有機(jī)會(huì)把事件和委托總結(jié)一下。

轉(zhuǎn)載于:https://www.cnblogs.com/qtiger/p/5834320.html

總結(jié)

以上是生活随笔為你收集整理的多线程总结之旅(12):跨线程调用控件的几种方式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。