栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > .Net

c#:深入理解SynchronizationContext

.Net 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

c#:深入理解SynchronizationContext

环境:

  • window10
  • vs2019
  • .net core 3.1
  • dnSpy v6.1.4 (.NET Core)
  • ILSpy版本6.1.0.5902

参考:《C# SynchronizationContext线程上下文简单说明》

顺便说下: 单独看SynchronizationContext意义不大,因为它是一个基类,在真正使用它的时候一般都要继承并覆盖其方法的(如:winform)。

一、为什么需要SynchronizationContext?

问题是这样的:在winform中窗体的控件都是由UI线程创建的,当我们点击按钮后如果有耗时操作的话,我们肯定需要单独启动线程去运算,运算完了之后又要访问窗体控件将结果显示出来,但因为窗体控件是由UI线程创建的,所以,winform仅允许我们在UI线程中去操纵窗体控件。

所以就有了下面的常见代码:

private void button1_Click(object sender, EventArgs e)
{
    button1.Text = "运算中...";
    button1.Enabled = false;
    Task.Run(() =>
    {
        //耗时操作
        Thread.Sleep(3000);
        //运算完成
        button1.BeginInvoke((MethodInvoker)delegate
        {
            button1.Text = "点击运算";
            button1.Enabled = true;
        });
    });
}

现在尝试换一种写法,使用SynchronizationContext可以达到相同的效果:

private void button1_Click(object sender, EventArgs e)
{
    button1.Text = "运算中...";
    button1.Enabled = false;
    var ctx = SynchronizationContext.Current;
    Task.Run(() =>
    {
        //耗时操作
        Thread.Sleep(3000);
        //运算完成
        ctx.Send(state =>
        {
            button1.Text = "点击运算";
            button1.Enabled = true;
        }, null);
    });
}

从上面看,SynchronizationContext好像是将代码变得简洁了一些。当时微软推出SynchronizationContext的时候是想做一个多线程协同工作的标准(参考:《并行计算 SynchronizationContext 综述》)。

二、SynchronizationContext的特点
  • 首先,这是一个基类,它只提供了基本的实现,如果要使用它大多都需要继承并覆盖其中的方法;
  • 其次,它提供了一个在多个线程间同步工作的标准(比如:线程A需要线程B协助做一些事情等等)。
三、在控制台中自实现一个多线程同步模型

为了更好的理解SynchronizationContext,我们在控制台实现一个多线程同步模型,目的是让两个线程在执行的时候相互协作。整个过程模拟的是Winform事件处理代码,即上面的示例。