我有一些代码需要在与GUI不同的线程中运行,因为它当前导致表单在代码运行时冻结(10秒左右).
假设我以前从未创建过新的线程; 什么是如何在C#中使用.NET Framework 2.0或更高版本执行此操作的简单/基本示例?
Joe Albahari是开始阅读的好地方.
如果你想创建自己的线程,这很简单:
using System.Threading; new Thread(() => { Thread.CurrentThread.IsBackground = true; /* run your code here */ Console.WriteLine("Hello, world"); }).Start();
BackgroundWorker
似乎是你的最佳选择.
这是我的最小例子.单击按钮后,后台工作程序将开始在后台线程中工作,并同时报告其进度.它还将在工作完成后报告.
using System.ComponentModel; ... private void button1_Click(object sender, EventArgs e) { BackgroundWorker bw = new BackgroundWorker(); // this allows our worker to report progress during work bw.WorkerReportsProgress = true; // what to do in the background thread bw.DoWork += new DoWorkEventHandler( delegate(object o, DoWorkEventArgs args) { BackgroundWorker b = o as BackgroundWorker; // do some simple processing for 10 seconds for (int i = 1; i <= 10; i++) { // report the progress in percent b.ReportProgress(i * 10); Thread.Sleep(1000); } }); // what to do when progress changed (update the progress bar for example) bw.ProgressChanged += new ProgressChangedEventHandler( delegate(object o, ProgressChangedEventArgs args) { label1.Text = string.Format("{0}% Completed", args.ProgressPercentage); }); // what to do when worker completes its task (notify the user) bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler( delegate(object o, RunWorkerCompletedEventArgs args) { label1.Text = "Finished!"; }); bw.RunWorkerAsync(); }
注意:
为了简单起见,我使用C#的匿名方法将所有内容都放在单个方法中,但您总是可以将它们用于不同的方法.
在内部ProgressChanged
或
RunWorkerCompleted
处理程序中更新GUI是安全的
.但是,更新GUI DoWork
将导致
InvalidOperationException
.
该ThreadPool.QueueUserWorkItem是相当理想的简单的东西.唯一需要注意的是从另一个线程访问一个控件.
System.Threading.ThreadPool.QueueUserWorkItem(delegate { DoSomethingThatDoesntInvolveAControl(); }, null);
快速又脏,但它会起作用:
在顶部使用:
using System.Threading;
简单代码:
static void Main( string[] args ) { Thread t = new Thread( NewThread ); t.Start(); } static void NewThread() { //code goes here }
我把它扔进了一个新的控制台应用程序中
这是另一种选择:
Task.Run(()=>{ //Here is a new thread });
尝试使用BackgroundWorker类.您可以为代理人提供运行的内容,并在工作完成时收到通知.我链接到的MSDN页面上有一个示例.
如果你想得到一个值:
var someValue; Thread thread = new Thread(delegate() { //Do somthing and set your value someValue = "Hello World"; }); thread.Start(); while (thread.IsAlive) Application.DoEvents();
将该代码放在一个函数中(无法在与GUI相同的线程上执行的代码),并触发该代码的执行,如下所示.
Thread myThread= new Thread(nameOfFunction);
workerThread.Start();
在线程对象上调用start函数将导致在新线程中执行函数调用.
在这里,如何将线程与progressBar结合使用,仅用于了解线程的工作方式,形式为三个progressBar和4个按钮:
public partial class Form1 : Form { public Form1() { InitializeComponent(); } Thread t, t2, t3; private void Form1_Load(object sender, EventArgs e) { CheckForIllegalCrossThreadCalls = false; t = new Thread(birinicBar); //evry thread workes with a new progressBar t2 = new Thread(ikinciBar); t3 = new Thread(ucuncuBar); } public void birinicBar() //to make progressBar work { for (int i = 0; i < 100; i++) { progressBar1.Value++; Thread.Sleep(100); // this progressBar gonna work faster } } public void ikinciBar() { for (int i = 0; i < 100; i++) { progressBar2.Value++; Thread.Sleep(200); } } public void ucuncuBar() { for (int i = 0; i < 100; i++) { progressBar3.Value++; Thread.Sleep(300); } } private void button1_Click(object sender, EventArgs e) //that button to start the threads { t.Start(); t2.Start(); t3.Start(); } private void button4_Click(object sender, EventArgs e)//that button to stup the threads with the progressBar { t.Suspend(); t2.Suspend(); t3.Suspend(); } private void button2_Click(object sender, EventArgs e)// that is for contuniue after stuping { t.Resume(); t2.Resume(); t3.Resume(); } private void button3_Click(object sender, EventArgs e) // finally with that button you can remove all of the threads { t.Abort(); t2.Abort(); t3.Abort(); } }