简单理解线程同步上下文

为了线程安全,winform和wpf框架中规定只能使用UI线程操作控件,从其它线程上操作控件就会报跨线程异常。假如有这样一个场景:点击按纽,然后开始计算员工薪资,并将计算信息实时展示在一个文本框中,由于计算过程比较耗时,为了不让界面卡死,我们会将计算方法放在单独一个线程中。UI代码如下:

薪资计算类代码如下:

上面的代码就不过多解释了,相信大家都看的懂。按纽点击后,开启一个新线程,执行计算,并将更新UI的方法以委托的形式传给SalaryCalculator类。我们执行一下,如下:

不出意外,报错了,我们不能在新线程中更新UI线程。一般的做法,我们可以使用Invoke,这个大家应该都用烂了。改写下ShowMessage,代码如下:

除了以上办法,我们还可以使用SynchronizationContext来解决上面的问题。这个类,大家可能比较陌生, 我们来看一下它的定义,如下:

它的定义:提供在各种同步模型中传播同步上下文中的基本功能。其实它的含义就是对当前线程上下文的封装,或者叫当前线程所在环境的封装。封装的对象可以传递至其他线程,然后在其他线程中调用其Post或Send方法,以此来实现线程间的消息传播。我们使用SynchronizationContext修改上面的代码,得到的结果都是一样。代码如下:

上面的代码中,先通过SynchronizationContext.Current获取UI线程的同步上下文对象,然后在计算薪资的线程中使用这个对象的Post方法,这时控制是在UI线程的上下文中执行,所以不会报错。

讲到这里,其实SynchronizationContext的内容就讲完了,不过有个点可以再补充下。大家应该知道Task对象有一个ConfigureAwait()方法,用来配置是否同步上下文,我们到这个方法中看一下,代码如下:

continueOnCapturedContext尝试将延续任务封送回原始上下文件,默认为true。这里说的原始上下文,其实就是SynchronizationContext,即异步前(await)前所在的线程的同步上下文。我们将Calculate改成异步方法,代码如下:

我们知道,异步方法在遇到await之前都在当前线程中执行,当执行完await这行后,方法就会退出,然后会将await之后的代码封装成委托(可能不太准确,大概这个意思,会产生一个状态机类,不展开讨论)。在执行await时,默认会捕获当前的线程上下文,然后当执行完Task.Delay(1000)后,上面说的线程上下文就会将剩下的代码发回(Post/Send)自己的线程执行。大概像下面这个样子,代码如下:

上面代码不一定准确,只是想表达这个意思。如果我们不想剩下来的代码在原来的上下文中执行,可以将continueOnCapturedContext设为false,这也是微软推荐的做法。不然会出现一些意想不到的情况,比如死锁。我们看一下调用的地方,代码如下:

我们配置了不捕获上下文,这时代码是正常运行的。我们再来演示一下经典的死锁问题吧,如果你还有兴趣就接着向下看吧。我们改造下上面的代码,改成同步等待,并默认捕获上下文。代码如下:

我们定义task变量,并去除ConfigureAwait(false),这样在Calculate中默认会捕获上下文。下面的task.Wait()会等待task完成,可是我们在线程上下文中又会执行Post方法,这时互相等待,造成死锁。解决办法:用到异步的地方都加上ConfigureAwait(false),另一个不要使用Wait方法,用异步就异步到底。

终于讲完了,今天讲的内容还是很简单,如果能帮到你一点点,我就会很开心的(能关注下就更好),哈哈。

最后PS一下这个demo的界面图吧,让你们看看我的设计能力~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/306884.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

修改手机屏幕刷新率_手机屏幕没有高刷新率算不上旗舰机?看看网友都是如何回答的...

近日Redmi K30 Pro的各种参数信息逐渐曝光,高通骁龙865处理器、LPDDR5内存、UFS3.1闪存、VC液冷散热、前置弹出式摄像头、多彩呼吸灯、Z轴线性马达等等参数都备受好评。唯独在提及屏幕时,60Hz的刷新率就让网友们不满意了。此前在K30的发布会上&#xff0…

持续交付二:为什么需要多个环境

关于开发测试生产需要多少个环境,因公司而异,这里分享一下我建议开发过程中使用的几个环境。Development环境,就是开发环境,程序写代码,写单元测试的环境,一般和IDE一起,经常是在调试模式下进行…

git revert 后再次merge_git如何回滚错误合并的分支

导读:分类:技术干货题目:git如何回滚错误合并的分支合并到线上分支出现问题的修复方式。场景线上分支:master你开发的分支:dev1同时开发的分支:dev2dev1分支开发的代码已经上线,并且已经merge到…

linux+c+逐行读文件内容,使用C ++中的ifstream逐行读取文件

在C 中逐行读取文件可以通过某些不同的方式完成。[快]循环使用std :: getline()最简单的方法是使用std :: getline()调用打开std :: ifstream和循环。 代码简洁易懂。#include std::ifstream file(FILENAME);if (file.is_open()) {std::string line;while (getline(file, line)…

如何区分netty是udp还是tcp_鲜奶粉还是大包粉,到底该如何区分?

100%的宝爸宝妈们都希望为宝宝挑选最营养、最新鲜的口粮,也相信让娃爸每周逛遍各大超市,只为了选两罐最新日期的奶粉,这种事情一定不止一个人做过!一直以来,人们对于“新鲜”有着亘古不变的追求。尤其是对待生活中的“…

Winform 进度条弹窗和任务控制

Winform 进度条弹窗和任务控制目录Winform 进度条弹窗和任务控制一、弹窗前台二、弹窗后台三、使用方法四、效果展示和代码地址独立观察员 2020 年 11 月 17 日最近要给一个 Winform 项目添加功能,需要一个能显示进度条的弹窗,还要求能够中止任务&#x…

c语言prime函数怎么用_C语言 要发就发

点击上方“蓝字”关注我们愉快的一天,不得不做的三件事:种田,锄地,整代码!!!【题目】“1898——要发就发”。请将不超过1993的所有素数从小到大排成第一行,第二行上的每个数都等于它…

linux如何使用vnc远程登录,如何使用Xmanager及VNC登录远程桌面

如何调用远程桌面,比较常见的有两种方式:Xmanager及VNC正好今天鼓捣了一下,特整理如下:XmanagerXmanager的调用也有两种方式:一、直接在Xshell中调用这时需设置会话属性,如下图所示,需在“隧道”…

python自然语言处理_python

chinese-xinhua/ | - data/ 汉字例子: { "word": "吖", "oldword": "吖", "strokes": "6", "pinyin": "ā", "radicals": "口", "explanation": &…

别在.NET死忠粉面前黑.NET5,它未来可期!

期盼已久的.NET5,终于在11月11日正式发布,整个.NET社区都为之沸腾,知乎、博客园、QQ群、微信群,随处可见.NET5 的热议,作为.NET死忠粉,我也挺兴奋的。然而一片欢歌笑语中总有一些很不和谐的声音&#xff0c…

c#物联网_C# 基础知识系列- 16 开发工具篇

0. 前言 这是C# 基础知识系列的最后一个内容讲解篇,下一篇是基础知识-实战篇。这一篇主要讲解一下C#程序的结构和主要编程工具。 1. 工具 工欲善其事必先利其器,在实际动手之前我们先来看看想要编写一套C#程序需要做哪些准备吧。 1.1 选择 C# 的sdk在之前…

接口幂等设计探索实践

幂等性原本是数学上的概念,即使公式:f(x)f(f(x)) 能够成立的数学性质。用在编程领域,则意为对同一个系统,使用同样的条件,一次请求和重复的多次请求对系统资源的影响是一致的、或者说是符合预期的。背景稳定性设计第一…

Windows 7 安装 .NET 5 / .NET Core 3.1 环境的方法和依赖文件

随着 .NET 5 正式版的发布,越来越多的人开始向 .NET 5 、.NET Core 平台迁移。尽管微软已经在 2020 年 1 月 14 日停止了对 Windows 7 的支持,但仍有大批客户的操作系统对 Windows 7 恋恋不舍。为此,我们需要解决 .NET 5 运行时(R…

easyui 动态设置单元格控件_动态显示最大最小值的折线图

小伙伴们好啊,今天和大家分享一个图表有关的知识。折线图想必大家已经司空见惯,今天就要在简单的折线上,做出不简单的效果。用动态折线图,展示一周销售的变化,并且自动突出最大最小值。1、准备数据源以某家水果店1月份…

WebBenchmark动态测试Webapi

在编写Webapi测试用例的时候都是定义固定的测试数据,但这样的测试只能针对单一数据。为了更好的模拟实际情况,往往需要进行动态数据测试;通过动态数据测试可以更好的测出服务在不同数据情况下的处理能力。WebBenchmark支持动态数据函数&#…

linux开发需要学习什么,linux开发需要掌握哪些知识?

原标题:linux开发需要掌握哪些知识?嵌入式linux开发的应用是非常广泛的。而且linux是开源的,各种技术也是非常成熟的。不过很多初学者在学习linux开发过程中感觉非常难,那么对于linux开发需要掌握哪些知识呢?1.Linux是…

csv 字符串_python3从零学习-5.5.1、CSV 文件读写

源代码: Lib/csv.py模块内容csv 模块定义了以下函数:csv.reader(csvfile, dialectexcel, **fmtparams)返回一个 reader 对象,该对象将逐行遍历 csvfile。csvfile 可以是任何对象,只要这个对象支持 iterator 协议并在每次调用 __ne…

持续交付三:动手自动化“开发”—“测试”

前两篇博文中提到Development,QA,Staging,Production四个环境,也说明了源代码的分支和四个环境的对应关系,本篇博文聊一下,怎么把源码自动化发布到对应的环境中。市面上主流的DevOpt工具都支持这些功能,github,gitlab,…

使用WebBenchmark对webapi进行管理和性能测试

WebBenchmark是基于beetlex开发的webapi管理和性能测试软件,最新版本1.0.3可以独立运行在linux/windows中,并不再需要安装.net core运行环境。部署可以通过以下地址下载最新版本:https://github.com/IKende/WebBenchmark可以根据需要下载linux64或win64运…

三维叉乘怎么算_奇技淫巧系列:向量叉乘

​一般我们在解决立体几何题目时会选择建立坐标系,因为这样做比较保险也有固定套路。很多时候这些题目要求你计算某一个面的法向量(normal vector),这在高中阶段也是有固定方法的,我们这里想要介绍的是一种更高级也更迅…