[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));
// 普通线程
private void btn1_Click(object sender, EventArgs e)
{
progressBar.Value = 0;
Thread tt = new Thread(new ThreadStart(DoWork1));
tt.Name = "不带参数普通线程";
tt.Start();
Thread t = new Thread(new ParameterizedThreadStart(DoWork2));
t.Name = "带参数普通线程";
t.IsBackground = true;
t.Start(100);
_msg += "当前线程的执行状态:" + t.IsAlive + "\r\n";
_msg += "当前托管线程的唯一标识:" + t.ManagedThreadId + "\r\n";
_msg += "线程名称:" + t.Name + "\r\n";
_msg += "当前线程的状态:" + t.ThreadState;
MessageBox.Show("消息:\r\n" + _msg, "提示", MessageBoxButtons.OK);
}
// 线程方法
private void DoWork1()
{
for (int i = 0; i < 100; i++)
{
// 跨线程访问 UI,BeginInvoke 采用异步委托
progressBar.BeginInvoke(new EventHandler((sender, e) =>
{
progressBar.Value = i;
}), null);
}
}
// 线程方法
private void DoWork2(object obj)
{
for (int i = 0; i < (int)obj; i++)
{
progressBar.BeginInvoke(new EventHandler((sender, e) =>
{
progressBar.Value = i;
}), null);
}
}
普通线程
二 线程池
public static bool QueueUserWorkItem(WaitCallback);
public static bool QueueUserWorkItem(WaitCallback, object);
线程池默认为后台线程(IsBackground)
private void btn3_Click(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(DoWork2, 100);
// 或者
ThreadPool.QueueUserWorkItem((s) =>
{
int minWorkerThreads, minCompletionPortThreads, maxWorkerThreads, maxCompletionPortThreads;
ThreadPool.GetMinThreads(out minWorkerThreads, out minCompletionPortThreads);
ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxCompletionPortThreads);
MessageBox.Show(String.Format("WorkerThreads = {0} ~ {1}, CompletionPortThreads = {2} ~ {3}",
minWorkerThreads, maxWorkerThreads, minCompletionPortThreads, maxCompletionPortThreads));
DoWork2(100);
});
}
// 线程方法
private void DoWork2(object obj)
{
for (int i = 0; i < (int)obj; i++)
{
// Thread.Sleep(50);
progressBar.BeginInvoke(new EventHandler((sender, e) =>
{
progressBar.Value = i;
}), null);
}
}
线程池
三 BackgroundWorker
private void btn4_Click(object sender, EventArgs e)
{
progressBar.Value = 0;
BackgroundWorker bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;// 是否报告进度更新
// 线程执行
bw.DoWork += new DoWorkEventHandler((obj, args) =>
{
for (int i = 0; i < 100; i++)
{
bw.ReportProgress(i);
}
});
// UI主线程显示进度
bw.ProgressChanged += (obj, progressChangedEventArgs) =>
{
progressBar.Value = progressChangedEventArgs.ProgressPercentage;
};
// 线程执行完成后的回调函数
bw.RunWorkerCompleted += (obj, runWorkerCompletedEventArgs) =>
{
MessageBox.Show("子线程执行完成!");
};
if (!bw.IsBusy)
{
bw.RunWorkerAsync();
}
}
BackgroundWorker
三 Task(.NET 4.0以上版本)
参考博客 http://www.cnblogs.com/luxiaoxun/p/3280146.html
private void btn5_Click(object sender, EventArgs e)
{
progressBar.Value = 0;
Task<bool> t = new Task<bool>(maxValue => DoWork((int)maxValue), progressBar.Maximum);
t.Start();
t.Wait();
// 任务完成后继续延续任务
Task cwt = t.ContinueWith(task => MessageBox.Show("The result is " + t.Result));
}
// 线程方法
private bool DoWork(int maxValue)
{
for (int n = 0; n < maxValue; n++)
{
progressBar.BeginInvoke(new EventHandler((sender, e) =>
{
progressBar.Value = n;
}), null);
} return true;
}
Task
四 异步委托
参考博客 http://www.cnblogs.com/luxiaoxun/p/3280146.html
public delegate string MyDelegate(object arg); private void btn6_Click(object sender, EventArgs e)
{
MyDelegate myDelegate = new MyDelegate(DoWork3);
IAsyncResult result = myDelegate.BeginInvoke(100, DoWork2Callback, "回调函数参数"); // 异步执行完成
string resultStr = myDelegate.EndInvoke(result);
} // 线程函数
private string DoWork3(object arg)
{
for (int n = 0; n < (int)arg; n++)
{
progressBar.BeginInvoke(new EventHandler((sender, e) =>
{
progressBar.Value = n;
}), null);
} return "Finished";
} // 异步回调函数
private void DoWork2Callback(IAsyncResult arg)
{
MessageBox.Show(arg.AsyncState.ToString());
}
异步委托
五 附 跨线程访问UI之 SynchronizationContext (同步上下文)
private void btn2_Click(object sender, EventArgs e)
{
SynchronizationContext context = SynchronizationContext.Current;
new Thread(() =>
{
for (int i = 0; i < 100; i++)
{
// Send方法是发送一个异步请求消息
//context.Send((s) =>
//{
// progressBar.Value = i;
//}, null);
// Post方法是发送一个同步请求消息
context.Post((s) =>
{
progressBar.Value = i;
}, null);
}
}).Start();
}
SynchronizationContext
六 参考资料:
☆多线程讲解 http://www.w3cschool.cc/csharp/csharp-multithreading.html
☆http://www.cnblogs.com/luxiaoxun/p/3280146.html
[C#] 多线程总结(结合进度条)的更多相关文章
- (委托事件处理)关于多线程执行显示进度条的实例(转)&&线程间操作无效: 从不是创建控件“rtxtEntryNO”的线程访问它。
关于多线程执行显示进度条的实例! 之前回答了一篇关于怎么在线程中操作进度条的帖子,估计有人看的不是很明白今天没事,写了一个小小的实例,很简单,就2个文件权当抛砖引玉,希望有更好解决方案的人发表一下意见 ...
- C#编程总结(四)多线程应用(进度条的编程问题)——转自http://www.cnblogs.com/yank/p/3232955.html
多线程应用 多线程应用很广泛,简单总结了一下: 1)不阻断主线程,实现即时响应,由后台线程完成特定操作2)多个线程,完成同类任务,提高并发性能3)一个任务有多个独立的步骤,多个线程并发执行各子任务,提 ...
- 赵雅智_android多线程下载带进度条
progressBar说明 在某些操作的进度中的可视指示器,为用户呈现操作的进度,还它有一个次要的进度条,用来显示中间进度,如在流媒体播放的缓冲区的进度. 一个进度条也可不确定其进度.在不确定模式下, ...
- Python:如何显示进度条
首先,推荐一个组件:progressive 效果如下: 进度条和一般的print区别在哪里呢? 答案就是print会输出一个\n,也就是换行符,这样光标移动到了下一行行首,接着输出,之前已经通过std ...
- C# 通过线程来控制进度条(转)--讲解多线程对界面的操作
// 通过创建委托解决传递参数问题 private void _btnRun_Click( object sender, System.EventArgs e ) { RunTaskDelegate ...
- C# 通过委托控制进度条以及多线程更新控件
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- Android开发之多线程下载、断点续传、进度条和文本显示
代码实现了在Android环境下的多线程下载.断点续传.进度条显示和文本显示百分数: import java.io.BufferedReader; import java.io.File; impor ...
- ASP.NET 多线程 监控任务执行情况,并显示进度条
关于多线程的基本概念和知识在本文中不多讲,而且我懂的也不是很透,说的太多误人子弟...对于我来说,做本文提到的功能够用就行,等实现其他效果不够用的时候,再深入研究 推荐看园子里的两篇博客应该就有个基本 ...
- WPF多线程下载文件,有进度条
//打开对话框选择文件 private void OpenDialogBox_Click(object sender, RoutedEventArgs e) { ...
随机推荐
- Angular2开发笔记
Problem 使用依赖注入应该注意些什么 服务一般用来做什么 指令一般用来做什么 angular2如何提取公共组件 angular2为什么不需要提公共组件 父组件与子组件之间如何通讯 什么时候应该使 ...
- CSS样式重置(转)
body,h1,h2,h3,h4,h5,h6,dl,dt,dd,ul,ol,li,th,td,p,blockquote,pre,form,fieldset,legend,input,button,te ...
- 我理解的MVC
前言 前一阶段对MVC模式及其衍生模式做了一番比较深入的研究和实践,这篇文章也算是一个阶段性的回顾和总结. 经典MVC模式 经典MVC模式中,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的 ...
- Highcharts中国地图热力图
最近有个项目需要将MC销量按大陆各省统计,并以中国地图人力图效果显示.由于项目一直使用Highcharts进行图表的统计,故采用Highmaps来实现. 效果如下: 1)中国各个省.直辖市.自治区: ...
- 让你从零开始学会写爬虫的5个教程(Python)
写爬虫总是非常吸引IT学习者,毕竟光听起来就很酷炫极客,我也知道很多人学完基础知识之后,第一个项目开发就是自己写一个爬虫玩玩. 其实懂了之后,写个爬虫脚本是很简单的,但是对于新手来说却并不是那么容易. ...
- 实现php连接memcached
准备工作: 实现lnmp环境 给php添加模块,so库 下载扩展包:memcache-2.2.5.tgz wget http://pecl.php.net/get/memcache-2.2.5.tgz
- TCP/IP之TCP_NODELAY与TCP_CORK
TCP/IP之Nagle算法与40ms延迟提到了Nagle 算法.这样虽然提高了网络吞吐量,但是实时性却降低了,在一些交互性很强的应用程序来说是不允许的,使用TCP_NODELAY选项可以禁止Nagl ...
- IOS开发之—— 在AFN基础上进行的网络请求的封装
网络请求的思路:如果请求成功的话AFN的responseObject就是解析好的. 1发送网络请求:get/post/或者别的 带上URL,需要传的参数 2判断后台网络状态码有没有请求成功: 3 请求 ...
- 我的MYSQL学习心得(三) 查看字段长度
我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...
- 关于HTML语义化的一些理解
语义化这个词我想大家都看到了无数次,特别是在一些招聘广告上. 其实我自己也是,不过每次看到都觉得是那些招聘公司复制的,其实他们根本说不清语义化是什么,而且也根本不看重. 所以我一直也没把这东西当回事过 ...