免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
多線程編程(4):多線程與UI操作
為了讓程序盡快響應用戶操作,在開發(fā)Windows應用程序時經(jīng)常會使用到線程。對于耗時的操作如果不使用線程將會是UI界面長時間處于停滯狀態(tài),這種情況是用戶非常不愿意看到的,在這種情況下我們希望使用線程來解決這個問題。
下面是一個使用多線程操作界面UI的代碼:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace ThreadPoolDemo
{
public partial class ThreadForm : Form
{
public ThreadForm()
{
InitializeComponent();
}
private void btnThread_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(Run));
thread.Start();
}
private void Run()
{
while (progressBar.Value < progressBar.Maximum)
{
progressBar.PerformStep();
}
}
}
}
程序的界面如下:
我們的本意是點擊“啟動”按鈕來啟動模擬一個操作,在進度條中顯示操作的總體進度。不過如果我們真的點擊“啟動”按鈕會很失望,因為它會拋出一個System.InvalidOperationException異常,異常描述就是“線程間操作無效: 從不是創(chuàng)建控件'progressBar’的線程訪問它?!?div style="height:15px;">
CheckForIllegalCrossThreadCalls屬性
之所以會出現(xiàn)這樣的情況是因為在.NET中做了限制,不允許在調試環(huán)境下使用線程訪問并非它自己創(chuàng)建的UI控件,這么做可能是怕在多線程環(huán)境下對界面控件進行操作會出現(xiàn)不可預知的情況,如果開發(fā)者可以確認自己的代碼操作界面不會出現(xiàn)問題,可以用比較簡單的方法解決,那就是設置CheckForIllegalCrossThreadCalls這個靜態(tài)屬性,它默認是true,如果將其設為false的話,以后在多線程環(huán)境下操作界面也不會拋出異常了,我們上面的代碼可以修改為:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace ThreadPoolDemo
{
public partial class ThreadForm : Form
{
public ThreadForm()
{
InitializeComponent();
}
private void btnThread_Click(object sender, EventArgs e)
{
//指示是否對錯誤線程的調用,即是否允許在創(chuàng)建UI的線程之外訪問線程
CheckForIllegalCrossThreadCalls = false;
Thread thread = new Thread(new ThreadStart(Run));
thread.Start();
}
private void Run()
{
while (progressBar.Value < progressBar.Maximum)
{
progressBar.PerformStep();
}
}
}
}
這樣再執(zhí)行程序就不會拋出異常了。
不過使用上面的代碼我們可能還有些犯嘀咕,畢竟是不允許直接在線程中直接操作界面的,那么我們還可以用Invoke方法。
Invoke方法來操作界面
下面是一個例子:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace ThreadPoolDemo
{
public partial class ThreadForm : Form
{
//定義delegate以便Invoke時使用
private delegate void SetProgressBarValue(int value);
public ThreadForm()
{
InitializeComponent();
}
private void btnThread_Click(object sender, EventArgs e)
{
progressBar.Value = 0;
//指示是否對錯誤線程的調用,即是否允許在創(chuàng)建UI的線程之外訪問線程
//CheckForIllegalCrossThreadCalls = false;
Thread thread = new Thread(new ThreadStart(Run));
thread.Start();
}
//使用線程來直接設置進度條
private void Run()
{
while (progressBar.Value < progressBar.Maximum)
{
progressBar.PerformStep();
}
}
private void btnInvoke_Click(object sender, EventArgs e)
{
progressBar.Value = 0;
Thread thread = new Thread(new ThreadStart(RunWithInvoke));
thread.Start();
}
//使用Invoke方法來設置進度條
private void RunWithInvoke()
{
int value = progressBar.Value;
while (value< progressBar.Maximum)
{
//如果是跨線程調用
if (InvokeRequired)
{
this.Invoke(new SetProgressBarValue(SetProgressValue), value++);
}
else
{
progressBar.Value = ++value;
}
}
}
//跟SetProgressBarValue委托相匹配的方法
private void SetProgressValue(int value)
{
progressBar.Value = value;
}
}
}
這個方法的功能跟上面的操作是一樣的,只不過不需要設置CheckForIllegalCrossThreadCalls屬性,而且還不會拋出異常,當然除了上面的方法之外,還可以使用BackgroundWorker類來完成同樣的功能。
BackgroundWorker類操作界面
因為使用BackgroundWorker類操作UI界面的例子周公博客上已經(jīng)有過例子,所以這里的例子代碼注釋比較簡單,讀者可以看周公以前的示例,這次所使用的代碼示例如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace ThreadPoolDemo
{
public partial class ThreadForm : Form
{
//定義delegate以便Invoke時使用
private delegate void SetProgressBarValue(int value);
private BackgroundWorker worker;
public ThreadForm()
{
InitializeComponent();
}
private void btnThread_Click(object sender, EventArgs e)
{
progressBar.Value = 0;
//指示是否對錯誤線程的調用,即是否允許在創(chuàng)建UI的線程之外訪問線程
//CheckForIllegalCrossThreadCalls = false;
Thread thread = new Thread(new ThreadStart(Run));
thread.Start();
}
//使用線程來直接設置進度條
private void Run()
{
while (progressBar.Value < progressBar.Maximum)
{
progressBar.PerformStep();
}
}
private void btnInvoke_Click(object sender, EventArgs e)
{
progressBar.Value = 0;
Thread thread = new Thread(new ThreadStart(RunWithInvoke));
thread.Start();
}
//使用Invoke方法來設置進度條
private void RunWithInvoke()
{
int value = progressBar.Value;
while (value< progressBar.Maximum)
{
//如果是跨線程調用
if (InvokeRequired)
{
this.Invoke(new SetProgressBarValue(SetProgressValue), value++);
}
else
{
progressBar.Value = ++value;
}
}
}
//跟SetProgressBarValue委托相匹配的方法
private void SetProgressValue(int value)
{
progressBar.Value = value;
}
private void btnBackgroundWorker_Click(object sender, EventArgs e)
{
progressBar.Value = 0;
worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
//當工作進度發(fā)生變化時執(zhí)行的事件處理方法
worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
//當事件處理完畢后執(zhí)行的方法
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.WorkerReportsProgress = true;//支持報告進度更新
worker.WorkerSupportsCancellation = false;//不支持異步取消
worker.RunWorkerAsync();//啟動執(zhí)行
btnBackgroundWorker.Enabled = false;
}
//當事件處理完畢后執(zhí)行的方法
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
btnBackgroundWorker.Enabled=true;
}
//當工作進度發(fā)生變化時執(zhí)行的事件處理方法
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//可以在這個方法中與界面進行通訊
progressBar.Value = e.ProgressPercentage;
}
//開始啟動工作時執(zhí)行的事件處理方法
void worker_DoWork(object sender, DoWorkEventArgs e)
{
int value = progressBar.Value;
while (value < progressBar.Maximum)
{
worker.ReportProgress(++value);//匯報進度
}
}
}
}
當然,除了BackgroundWorker可以完成上面的功能之外,利用System.Windows.Forms.Timer類也能完場上面的功能,代碼如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace ThreadPoolDemo
{
public partial class ThreadForm : Form
{
//定義delegate以便Invoke時使用
private delegate void SetProgressBarValue(int value);
private BackgroundWorker worker;
public ThreadForm()
{
InitializeComponent();
}
private void btnThread_Click(object sender, EventArgs e)
{
progressBar.Value = 0;
//指示是否對錯誤線程的調用,即是否允許在創(chuàng)建UI的線程之外訪問線程
//CheckForIllegalCrossThreadCalls = false;
Thread thread = new Thread(new ThreadStart(Run));
thread.Start();
}
//使用線程來直接設置進度條
private void Run()
{
while (progressBar.Value < progressBar.Maximum)
{
progressBar.PerformStep();
}
}
private void btnInvoke_Click(object sender, EventArgs e)
{
progressBar.Value = 0;
Thread thread = new Thread(new ThreadStart(RunWithInvoke));
thread.Start();
}
//使用Invoke方法來設置進度條
private void RunWithInvoke()
{
int value = progressBar.Value;
while (value< progressBar.Maximum)
{
//如果是跨線程調用
if (InvokeRequired)
{
this.Invoke(new SetProgressBarValue(SetProgressValue), value++);
}
else
{
progressBar.Value = ++value;
}
}
}
//跟SetProgressBarValue委托相匹配的方法
private void SetProgressValue(int value)
{
progressBar.Value = value;
}
private void btnBackgroundWorker_Click(object sender, EventArgs e)
{
progressBar.Value = 0;
worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
//當工作進度發(fā)生變化時執(zhí)行的事件處理方法
worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
//當事件處理完畢后執(zhí)行的方法
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.WorkerReportsProgress = true;//支持報告進度更新
worker.WorkerSupportsCancellation = false;//不支持異步取消
worker.RunWorkerAsync();//啟動執(zhí)行
btnBackgroundWorker.Enabled = false;
}
//當事件處理完畢后執(zhí)行的方法
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
btnBackgroundWorker.Enabled=true;
}
//當工作進度發(fā)生變化時執(zhí)行的事件處理方法
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//可以在這個方法中與界面進行通訊
progressBar.Value = e.ProgressPercentage;
}
//開始啟動工作時執(zhí)行的事件處理方法
void worker_DoWork(object sender, DoWorkEventArgs e)
{
int value = progressBar.Value;
while (value < progressBar.Maximum)
{
worker.ReportProgress(++value);//匯報進度
}
}
//使用System.Windows.Forms.Timer來操作界面能
private void btnTimer_Click(object sender, EventArgs e)
{
progressBar.Value = 0;
//注意在.net中有多個命名空間下存在Timer類,為了便于區(qū)別,使用了帶命名空間形式
System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
timer.Interval = 1;
timer.Tick += new EventHandler(timer_Tick);
timer.Enabled = true;
}
//Timer中要定期執(zhí)行的方法
void timer_Tick(object sender, EventArgs e)
{
int value = progressBar.Value;
if (value < progressBar.Maximum)
{
progressBar.Value = value+100;
}
}
}
}
總結:本篇主要講述了使用線程操作Windows應用程序界面的方法,這些方法在編寫多線程的UI程序時可以參考。
本站僅提供存儲服務,所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
C#調用耗時函數(shù)時顯示進度條淺探
從不是創(chuàng)建控件的線程訪問控件(1)(原創(chuàng))
C#多線程解決界面卡死問題的完美解決方案 – 放肆雷特 | 胖子的技術博客
WPF 進度條
C#在后臺運行操作:BackgroundWorker的用法
C# 多線程實現(xiàn)ProgressBar效果
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服