[C#] 多线程总结(结合进度条)
线程生命周期(来源 w3cschool)
- 未启动状态:当线程实例被创建但 Start 方法未被调用时的状况。
- 就绪状态:当线程准备好运行并等待 CPU 周期时的状况。
- 不可运行状态:
- 已经调用 Sleep 方法
- 已经调用 Wait 方法
- 通过 I/O 操作阻塞
- 死亡状态:当线程已完成执行或已中止时的状况。
Thread 常用方法:
- public void Interrupt() 中断处于 WaitSleepJoin 线程状态的线程。
- public void Join() 在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻塞调用线程,直到某个线程终止为止。
- public void Start() 开始一个线程
- public static void Sleep(int millisecondsTimeout) 让线程暂停一段时间
一 普通线程
分为两种,一种是不需要给子线程传参数,Thread t = new Thread(new ThreadStart(void () target)); 另一种是要给子线程传一个参数,Thread t = new Thread(new ParameterizedThreadStart(void (object) target));
1 // 普通线程 2 private void btn1_Click(object sender, EventArgs e) 3 { 4 progressBar.Value = 0; 5 Thread tt = new Thread(new ThreadStart(DoWork1)); 6 tt.Name = "不带参数普通线程"; 7 tt.Start(); 8 Thread t = new Thread(new ParameterizedThreadStart(DoWork2)); 9 t.Name = "带参数普通线程"; 10 t.IsBackground = true; 11 t.Start(100); 12 _msg += "当前线程的执行状态:" + t.IsAlive + "\r\n"; 13 _msg += "当前托管线程的唯一标识:" + t.ManagedThreadId + "\r\n"; 14 _msg += "线程名称:" + t.Name + "\r\n"; 15 _msg += "当前线程的状态:" + t.ThreadState; 16 MessageBox.Show("消息:\r\n" + _msg, "提示", MessageBoxButtons.OK); 17 } 18 // 线程方法 19 private void DoWork1() 20 { 21 for (int i = 0; i < 100; i++) 22 { 23 // 跨线程访问 UI,BeginInvoke 采用异步委托 24 progressBar.BeginInvoke(new EventHandler((sender, e) => 25 { 26 progressBar.Value = i; 27 }), null); 28 } 29 } 30 // 线程方法 31 private void DoWork2(object obj) 32 { 33 for (int i = 0; i < (int)obj; i++) 34 { 35 progressBar.BeginInvoke(new EventHandler((sender, e) => 36 { 37 progressBar.Value = i; 38 }), null); 39 } 40 } 41
二 线程池
public static bool QueueUserWorkItem(WaitCallback);
public static bool QueueUserWorkItem(WaitCallback, object);
线程池默认为后台线程(IsBackground)
1 private void btn3_Click(object sender, EventArgs e) 2 { 3 ThreadPool.QueueUserWorkItem(DoWork2, 100); 4 // 或者 5 ThreadPool.QueueUserWorkItem((s) => 6 { 7 int minWorkerThreads, minCompletionPortThreads, maxWorkerThreads, maxCompletionPortThreads; 8 ThreadPool.GetMinThreads(out minWorkerThreads, out minCompletionPortThreads); 9 ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxCompletionPortThreads); 10 MessageBox.Show(String.Format("WorkerThreads = {0} ~ {1}, CompletionPortThreads = {2} ~ {3}", 11 minWorkerThreads, maxWorkerThreads, minCompletionPortThreads, maxCompletionPortThreads)); 12 DoWork2(100); 13 }); 14 } 15 // 线程方法 16 private void DoWork2(object obj) 17 { 18 for (int i = 0; i < (int)obj; i++) 19 { 20 // Thread.Sleep(50); 21 progressBar.BeginInvoke(new EventHandler((sender, e) => 22 { 23 progressBar.Value = i; 24 }), null); 25 } 26 } 27
三 BackgroundWorker
1 private void btn4_Click(object sender, EventArgs e) 2 { 3 progressBar.Value = 0; 4 BackgroundWorker bw = new BackgroundWorker(); 5 bw.WorkerReportsProgress = true;// 是否报告进度更新 6 // 线程执行 7 bw.DoWork += new DoWorkEventHandler((obj, args) => 8 { 9 for (int i = 0; i < 100; i++) 10 { 11 bw.ReportProgress(i); 12 } 13 }); 14 // UI主线程显示进度 15 bw.ProgressChanged += (obj, progressChangedEventArgs) => 16 { 17 progressBar.Value = progressChangedEventArgs.ProgressPercentage; 18 }; 19 // 线程执行完成后的回调函数 20 bw.RunWorkerCompleted += (obj, runWorkerCompletedEventArgs) => 21 { 22 MessageBox.Show("子线程执行完成!"); 23 }; 24 if (!bw.IsBusy) 25 { 26 bw.RunWorkerAsync(); 27 } 28 }
三 Task(.NET 4.0以上版本)
参考博客 http://www.cnblogs.com/luxiaoxun/p/3280146.html
1 private void btn5_Click(object sender, EventArgs e) 2 { 3 progressBar.Value = 0; 4 Task<bool> t = new Task<bool>(maxValue => DoWork((int)maxValue), progressBar.Maximum); 5 t.Start(); 6 t.Wait(); 7 // 任务完成后继续延续任务 8 Task cwt = t.ContinueWith(task => MessageBox.Show("The result is " + t.Result)); 9 } 10 // 线程方法 11 private bool DoWork(int maxValue) 12 { 13 for (int n = 0; n < maxValue; n++) 14 { 15 progressBar.BeginInvoke(new EventHandler((sender, e) => 16 { 17 progressBar.Value = n; 18 }), null); 19 } 20 21 return true; 22 } 23
四 异步委托
参考博客 http://www.cnblogs.com/luxiaoxun/p/3280146.html
1 public delegate string MyDelegate(object arg); 2 3 private void btn6_Click(object sender, EventArgs e) 4 { 5 MyDelegate myDelegate = new MyDelegate(DoWork3); 6 IAsyncResult result = myDelegate.BeginInvoke(100, DoWork2Callback, "回调函数参数"); 7 8 // 异步执行完成 9 string resultStr = myDelegate.EndInvoke(result); 10 } 11 12 // 线程函数 13 private string DoWork3(object arg) 14 { 15 for (int n = 0; n < (int)arg; n++) 16 { 17 progressBar.BeginInvoke(new EventHandler((sender, e) => 18 { 19 progressBar.Value = n; 20 }), null); 21 } 22 23 return "Finished"; 24 } 25 26 // 异步回调函数 27 private void DoWork2Callback(IAsyncResult arg) 28 { 29 MessageBox.Show(arg.AsyncState.ToString()); 30 }
五 附 跨线程访问UI之 SynchronizationContext (同步上下文)
1 private void btn2_Click(object sender, EventArgs e) 2 { 3 SynchronizationContext context = SynchronizationContext.Current; 4 new Thread(() => 5 { 6 for (int i = 0; i < 100; i++) 7 { 8 // Send方法是发送一个异步请求消息 9 //context.Send((s) => 10 //{ 11 // progressBar.Value = i; 12 //}, null); 13 // Post方法是发送一个同步请求消息 14 context.Post((s) => 15 { 16 progressBar.Value = i; 17 }, null); 18 } 19 }).Start(); 20 } 21
六 参考资料:
☆多线程讲解 http://www.w3cschool.cc/csharp/csharp-multithreading.html
文章作者:Memento
博客地址:http://www.cnblogs.com/Memento/
版权声明:Memento所有文章遵循创作共用版权协议,要求署名、非商业、保持一致。在满足创作共用版权协议的基础上可以转载,但请以超链接形式注明出处。
博客地址:http://www.cnblogs.com/Memento/
版权声明:Memento所有文章遵循创作共用版权协议,要求署名、非商业、保持一致。在满足创作共用版权协议的基础上可以转载,但请以超链接形式注明出处。