线程同步 SynchronizationContext 初识

什么是 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中

.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 中管理跨线程同步操作的重要工具。它提供了多种机制,可以防止并发问题并简化多线程编程。

 

posted @ 2024-03-20 15:07  卖雨伞的小男孩  阅读(206)  评论(0编辑  收藏  举报