善用 SPINWAIT 处理 线程空转 以利提升效能
来源:互联网 发布:淘宝牛仔女裤 编辑:程序博客网 时间:2024/04/29 21:30
当我们在处理一个线程时,若需要同步等待时,以往可能会常用 Thread.Sleep,但 Thread.Sleep 会消耗 CPU 的时间配置,所以我们可以使用 Thread.SpinWait 方法 、SpinWait 结构
在 .NET4.0 以前,可以使用 Thread.SpinWait 方法
下图出自http://msdn.microsoft.com/zh-tw/library/system.threading.thread.spinwait.aspx
在 .NET4.0 以后,可以使用 SpinWait 结构
下图出自http://msdn.microsoft.com/zh-tw/library/ee722114.aspx
下图出自http://msdn.microsoft.com/zh-tw/library/system.threading.spinwait.aspx
看来,MSDN 则是建议使用 SpinWait 结构
来看个例子:
以往我常用 Stopwatch 来搭配 Thread.Sleep 来达到空转等待的目的
public void Start(Action action){ if (this.IsRunning) { return; } this.IsRunning = true; Task.Factory.StartNew(() => { Stopwatch watch = new Stopwatch(); while (this.IsRunning) { watch.Restart(); action.Invoke(); while (watch.ElapsedMilliseconds < this.Interval) { Thread.Sleep(1); } } });}
把 this.Interval = 1 观察任务管理器结果,CPU 大约用掉了 2% (这在不同的机器会有不同的结果)。
若是把 Thread.Sleep(1) 拿掉,CPU 负荷将近半载
现在则把 Thread.Sleep拿掉,改用 SpinWait.SpinUntil 来运行空转等待。
第一个参数是离开空转的条件,第二个参数是离开空转的时间,只要任一参数满足,则离开空转。
public void Start(Action action){ if (this.IsRunning) { return; } this.IsRunning = true; Task.Factory.StartNew(() => { while (this.IsRunning) { action.Invoke(); SpinWait.SpinUntil(() => !this.IsRunning, this.Interval); } });}
我们同样用 this.Interval = 1 来观察空转的效果,结果是 0%,很明显的这样的写法的确是胜于上一个方法。
结论:
PS.基本上 UI 更新的越快CPU飙的越高,若没有空转 UI 没办法更新。
所以我们可以把 Thread.Sleep(1) 可以换成 SpinWait.SpinUntil(() => false, 1)
完整程序代码,它没有防呆,请不要将 TextBox 设成 0 或空。
public class Polling{ private int _interval = 1000; public int Interval { get { return _interval; } set { _interval = value; } } public bool IsRunning { get; internal set; } public void Start(Action action) { if (this.IsRunning) { return; } this.IsRunning = true; Task.Factory.StartNew(() => { while (this.IsRunning) { action.Invoke(); SpinWait.SpinUntil(() => !this.IsRunning, this.Interval); } }); } public void Stop() { if (!this.IsRunning) { return; } this.IsRunning = false; }}
建立Winform项目,建立以下控件
客户端,调用方式,这里是使用 SynchronizationContext 更新 UI
public partial class Form1 : Form{ public Form1() { InitializeComponent(); m_SynchronizationContext = SynchronizationContext.Current; } private SynchronizationContext m_SynchronizationContext; private Polling _polling = new Polling(); private int _counter = 0; private void button1_Click(object sender, EventArgs e) { this._polling.Interval = int.Parse(this.textBox1.Text); this._polling.Start(() => { this._counter++; m_SynchronizationContext.Post(a => { this.label1.Text = this._counter.ToString(); }, null); }); } private void button2_Click(object sender, EventArgs e) { this._polling.Stop(); }}
- 善用 SPINWAIT 处理 线程空转 以利提升效能
- SpinWait
- 利用SpinWait进行工作线程同步
- SQL语句优化提升整体效能
- 黑暗中的管理效能提升总结
- .NET 阻止线程执行上下文流动,以提升程序“性能”。
- 如何善用肢体语言提升销售能力
- Nginx服务器优化,以提升服务器的处理性能
- 线程/进程/系统效能的API
- 如何提升 SQL Server 2005 的查询效能
- 生涯四度——提升你的生活效能
- 传统企业转向互联网,如何快速提升研发效能?
- 传统企业转向互联网_如何快速提升研发效能?
- 【转】效能...效能...效能!!
- 以信息化提升企业竞争力
- 善用科技–通过软件来提升你的效率
- 善用科技–通过软件来提升你的效率
- 善用科技–通过软件来提升你的效率
- 电信号码停机查询本机号码
- (ssl1759)求连通分量
- [李景山php]每天laravel[007]-laravel 中级任务翻译---简介
- 年薪5w和50w的人区别到底在哪?
- 数据流图的画法
- 善用 SPINWAIT 处理 线程空转 以利提升效能
- 不需要form,获取table所有数据,整合为json数据 传送给后台
- Spring MVC拦截器
- 关于getElementByClassName的兼容性问题
- 1072: [SCOI2007]排列perm
- SSD中ssd_detect调用caffe解读
- 内部查询处理器错误:查询处理器无法生成查询计划
- C++的cout高阶格式化操作
- 安装Composer