首页 > 其他分享 >线程同步 SynchronizationContext 初识

线程同步 SynchronizationContext 初识

时间:2024-03-20 15:11:06浏览次数:16  
标签:控件 Invoke SynchronizationContext InvokeRequired 初识 线程 ISynchronizeInvoke

什么是 SynchronizationContext?

SynchronizationContext 是 .NET 中的一个类,用于管理跨线程的同步操作。它提供了一种机制,使线程可以协调对共享资源的访问,从而防止并发问题。

SynchronizationContext 的工作原理

SynchronizationContext 与每个线程相关联。当线程执行时,它会使用关联的 SynchronizationContext 来协调对共享资源的访问。SynchronizationContext 负责将同步操作排队并以正确的顺序执行它们。

SynchronizationContext 的类型

.NET 中有两种主要的 SynchronizationContext 类型:

  • SynchronizationContext:这是基本类型,用于协调跨线程的同步操作。
  • TaskScheduler:这是 SynchronizationContext 的一个子类,用于协调使用 Task Parallel Library (TPL) 执行的异步操作。

使用 SynchronizationContext

可以使用以下方法使用 SynchronizationContext:

  • Current:获取当前线程的 SynchronizationContext。
  • Post:将一个委托排队在 SynchronizationContext 上执行。
  • Send:立即在 SynchronizationContext 上执行一个委托。

对于在WPF和winform中

System.Windows.Forms.WindowsFormsSynchronizationContext System.Windows.Threading.DispatcherSynchronizationContext

.Net在SynchronizationContext之前的线程同步

ISynchronizeInvoke 是 .NET 中的一个接口,它定义了一个方法,该方法用于在创建控件或元素的线程上异步调用委托。

ISynchronizeInvoke.InvokeRequired

InvokeRequired 属性指示当前线程是否与创建控件或元素的线程不同。如果 InvokeRequired 为 true,则必须使用 Invoke 方法在创建控件或元素的线程上执行操作。

ISynchronizeInvoke.Invoke

Invoke 方法将一个委托排队在创建控件或元素的线程上执行。该委托将在控件或元素的线程空闲时执行。

ISynchronizeInvoke 的实现

在 WinForms 中,Control 类实现了 ISynchronizeInvoke 接口。这意味着所有控件都具有 InvokeRequired 和 Invoke 方法。

在 WPF 中,Dispatcher 类实现了 ISynchronizeInvoke 接口。这意味着所有 DispatcherObject(包括控件和元素)都具有 InvokeRequired 和 Invoke 方法。

使用 ISynchronizeInvoke

可以使用以下方法使用 ISynchronizeInvoke

  1. 检查 InvokeRequired 属性以确定当前线程是否与创建控件或元素的线程不同。
  2. 如果 InvokeRequired 为 true,则使用 Invoke 方法将委托排队在创建控件或元素的线程上执行。

以下示例演示如何在 WinForms 中使用 ISynchronizeInvoke

private void Button1_Click(object sender, EventArgs e)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new Action(() => { this.Text = "Button clicked!"; }));
    }
    else
    {
        this.Text = "Button clicked!";
    }
}

 

以下示例演示如何在 WPF 中使用 ISynchronizeInvoke

private void Button1_Click(object sender, RoutedEventArgs e)
{
    if (Dispatcher.CurrentDispatcher.CheckAccess())
    {
        this.Text = "Button clicked!";
    }
    else
    {
        Dispatcher.CurrentDispatcher.Invoke(() => { this.Text = "Button clicked!"; });
    }
}

 

在winform和wpf举例

SynchronizationContext 的应用举例

SynchronizationContext 用于在 .NET 中管理跨线程的同步操作。它提供了一种机制,使线程可以协调对共享资源的访问,从而防止并发问题。

以下是一些 SynchronizationContext 的应用举例:

  • 更新 UI:在多线程应用程序中,必须使用 SynchronizationContext 来更新 UI 线程上的控件。这是因为控件只能在其创建的线程上进行修改。
  • 访问共享数据:如果多个线程访问共享数据,则必须使用 SynchronizationContext 来同步对该数据的访问。这可以防止数据损坏和并发问题。
  • 事件处理:在多线程应用程序中,事件处理程序可能会在不同的线程上被调用。SynchronizationContext 可用于确保事件处理程序在正确的线程上执行。
  • 异步编程:SynchronizationContext 可用于简化异步编程。它提供了一种机制,可以在完成异步操作后在正确的线程上执行回调。

示例

以下示例演示如何在 WinForms 中使用 SynchronizationContext 更新 UI:

private void Button1_Click(object sender, EventArgs e)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new Action(() => { this.Text = "Button clicked!"; }));
    }
    else
    {
        this.Text = "Button clicked!";
    }
}

 

在上面的示例中,InvokeRequired 属性用于检查当前线程是否与创建控件的线程不同。如果当前线程不同,则使用 Invoke 方法将委托排队在创建控件的线程上执行。

以下示例演示如何在 WPF 中使用 SynchronizationContext 更新 UI:

private void Button1_Click(object sender, RoutedEventArgs e)
{
    if (Dispatcher.CurrentDispatcher.CheckAccess())
    {
        this.Text = "Button clicked!";
    }
    else
    {
        Dispatcher.CurrentDispatcher.Invoke(() => { this.Text = "Button clicked!"; });
    }
}

 

在上面的示例中,CheckAccess 方法用于检查当前线程是否与创建控件的线程相同。如果当前线程不同,则使用 Invoke 方法将委托排队在创建控件的线程上执行。

结论

SynchronizationContext 是在 .NET 中管理跨线程同步操作的重要工具。它提供了多种机制,可以防止并发问题并简化多线程编程。

 

标签:控件,Invoke,SynchronizationContext,InvokeRequired,初识,线程,ISynchronizeInvoke
From: https://www.cnblogs.com/xietianjiao/p/18085277

相关文章

  • redis自学(22)Redis是单线程还是多线程?
    Redis是单线程还是多线程?Redis到底是单线程还是多线程? 如果仅仅聊Redis的核心的业务处理部分(命令处理),答案是单线程 如果是聊整个Redis那么答案是对线程在Redis版本迭代过程中,在两个重要的时间节点上引入了多线程的支持:Redisv4.0:引入多线程异步处理一些耗时较长的任务,......
  • JAVA 线程池SingleThreadExecutor实践教程
    SingleThreadExecutor是一个单线程的Executor,它使用单个工作线程来执行任务,保证所有任务按照指定顺序(FIFO,LIFO,优先级)执行。下面是使用SingleThreadExecutor的实践教程:步骤1:创建SingleThreadExecutor你可以使用Executors类提供的newSingleThreadExecutor方法来创......
  • JAVA线程池ScheduledThreadPool实践教程
    ScheduledThreadPool用于在给定的延迟之后,或者定期执行任务。以下是如何在Java中实践使用ScheduledThreadPool的步骤:步骤1:创建ScheduledThreadPool首先,使用Executors的newScheduledThreadPool方法来创建一个ScheduledThreadPool。参数是你想要在池中保持的线程数量。i......
  • 【Java初阶(一)】初识Java
    ❣博主主页:33的博客❣▶文章专栏分类:Java从入门到精通◀......
  • JAVASE各模块结构图:面向对象、常用类、多线程、异常、IO流、集合、网络编程
    ......
  • 深入浅出Java多线程(十三):阻塞队列
    引言大家好,我是你们的老伙计秀才!今天带来的是[深入浅出Java多线程]系列的第十三篇内容:阻塞队列。大家觉得有用请点赞,喜欢请关注!秀才在此谢过大家了!!!在多线程编程的世界里,生产者-消费者问题是一个经典且频繁出现的场景。设想这样一个情况:有一群持续不断地生产资源的线程(我们称之......
  • 初识C++(上)
    目录 1.引用1.1引用特性:1.2传引用传参1.3引用返回2.重要注意事项3.函数重载3.1重载原理 4.类的认识4.2 访问限定符号4.3 类的作用域4.4类的实例化5.对象 6.this指针6.1特性6.2注意事项 1.引用 相当与给某个变量取了一个别名,但是这前者和后......
  • CPU的核心数与线程数对性能的影响是什么
    ​我们经常在CPU的配置参数中看到核心数和线程数,那你知道CPU的核心数与线程数对性能的影响是什么呢?核心数和线程数是越多越好吗?要弄清楚这个问题,我们必须先了解以下几个基础知识。什么是CPU核心?CPU核心,也称为处理器核心,是CPU的基本处理单元。每个核心都包含独立的算术逻辑单元、......
  • 线程的引入以及进程和线程的区别
    线程的引入:在OS中引入线程,为了减少程序在并发执行时所付出的时空开销,使OS具有更好的并发性。进程的两个基本属性:进程是一个可拥有资源的独立单位;进程同时也是一个可独立调度和分派的基本单位。每个进程在系统中均有唯一的PCB,系统可根据PCB来感知进程的存在,也可以根据PCB中的信......
  • 多进程并发 v.s.多线程并发
    多进程并发v.s.多线程并发优缺点多进程的优点:独立性:每个进程都有独立的内存空间,相互之间不会影响,数据隔离性好。稳定性:一个进程崩溃通常不会影响其他进程,提高了系统的稳定性。简单的错误处理:进程之间的错误处理相对简单,一个进程崩溃通常只需要重启该进程即可。适用于CP......