当前位置: 首页 > ai >正文

C# Task 与 SynchronizationContext

示例代码

using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;namespace Test
{internal class Program{static void Main(string[] args){_mainThreadSynchronizationContext = new ThreadSynchronizationContext("main");_threadSynchronizationContext = new ThreadSynchronizationContext("thread");if (SynchronizationContext.Current == null){Console.WriteLine("Main SynchronizationContext.Current is null");}SynchronizationContext.SetSynchronizationContext(_mainThreadSynchronizationContext);if (SynchronizationContext.Current != null){Console.WriteLine("Main SynchronizationContext.Current is not null!");}Thread thread = new Thread(ThreadLoop);thread.Start();MainLoop();}private static ThreadSynchronizationContext _mainThreadSynchronizationContext;private static ThreadSynchronizationContext _threadSynchronizationContext;private static void MainLoop(){MainTest();while (true){Thread.Sleep(1);_mainThreadSynchronizationContext.Update();}}private static void ThreadLoop(){if (SynchronizationContext.Current == null){Console.WriteLine("Thread SynchronizationContext.Current is null");}SynchronizationContext.SetSynchronizationContext(_threadSynchronizationContext);if (SynchronizationContext.Current != null){Console.WriteLine("Thread SynchronizationContext.Current is not null");}Thread.Sleep(10000);ThreadTest();while (true){Thread.Sleep(1);_threadSynchronizationContext.Update();}}private static async Task MainTest(){Console.WriteLine($"MainTest {Thread.CurrentThread.ManagedThreadId}");await TaskNew();Console.WriteLine($"MainTest End {Thread.CurrentThread.ManagedThreadId}");}private static async Task ThreadTest(){Console.WriteLine($"ThreadTest {Thread.CurrentThread.ManagedThreadId}");await TaskNew();Console.WriteLine($"ThreadTest End {Thread.CurrentThread.ManagedThreadId}");}private static Task TaskNew(){return Task.Factory.StartNew(() =>{Console.WriteLine($"TaskNew Begin {Thread.CurrentThread.ManagedThreadId}");Thread.Sleep(5000);Console.WriteLine($"TaskNew End {Thread.CurrentThread.ManagedThreadId}");});}public class ThreadSynchronizationContext : SynchronizationContext{// 线程同步队列,发送接收socket回调都放到该队列,由poll线程统一执行private readonly ConcurrentQueue<Action> queue = new();private Action a;private string name;public ThreadSynchronizationContext(string name){this.name = name;}public void Update(){while (true){if (!this.queue.TryDequeue(out a)){return;}try{a();}catch (Exception e){Console.WriteLine(e);}}}public override void Post(SendOrPostCallback callback, object state){this.Post(() => callback(state));}public void Post(Action action){Console.WriteLine($"Post: {name}");this.queue.Enqueue(action);}}}
}

输出结果

Thread SynchronizationContext.Current is null
Thread SynchronizationContext.Current is not null
MainTest 1
TaskNew Begin 4
TaskNew End 4
Post: main
MainTest End 1
ThreadTest 3
TaskNew Begin 5
TaskNew End 5
Post: thread
ThreadTest End 3

SynchronizationContext

这个类的作用是将代码从一个线程转移到另外一个线程执行。
Send 表示同步执行代码快,会阻塞当前线程,直到Send执行完成。
Post 表示异步执行代码快,不阻塞当前线程。

SynchronizationContext.Current 与 SynchronizationContext.SetSynchronizationContext
这个静态属性与方法,是线程隔离的,也就是线程1 调用SynchronizationContext.SetSynchronizationContext。线程2 通过 SynchronizationContext.Current 是获取不到值的,从上面例子中也可以看出。

可以看到 SynchronizationContext 的源码,Send 方法是当前线程同步调用。Post 是从线程池中找一个线程进行调用。

SynchronizationContext.Current 这个值在不同环境中的主线程结果是不一样的。在控制台情况下默认是NULL,在WindowForm的情况下是 WindowsFormsSynchronizationContext。在Unity中是 UnitySynchronizationContext。

当通过await Task开启一个异步任务,当任务完成后会调用SynchronizationContext.Current.Post 方法。在例子中可以看出。如果SynchronizationContext.Current 是空,则会使用默认值SynchronizationContext对象。通过这个特性,重写SynchronizationContext 就可以让线程执行完成Task后,回调到原来线程进行执行,这个经常需要使用到。

http://www.xdnf.cn/news/7453.html

相关文章:

  • 文件包含靶场实现
  • 【移动应用安全】Android系统安全与保护机制
  • WPF技巧-常用的Converter集合(更新ing)
  • Spring Boot-Swagger离线文档(插件方式)
  • 【Redis】跳表结构
  • LSTM语言模型验证代码
  • springboot框架 集成海康ISUP-SDK 并实现 协议透传给设备下发指令!
  • 【鸿蒙开发】安全
  • centos 9 Kickstart + Ansible自动化部署 —— 筑梦之路
  • 软考软件评测师——数据库系统应用
  • spark-shuffle 类型及其对比
  • 新兴技术与安全挑战
  • Android7 Input(八)App Input事件接收器InputEventReceiver
  • 接口自动化可视化展示
  • CQF预备知识:Python相关库 —— 什么是 NumPy?
  • Linux网络基础全面解析:从协议分层到局域网通信原理
  • 【原创】ubuntu22.04下载编译AOSP 15
  • 杰里7006d日志分析
  • React 第四十四节Router中 usefetcher的使用详解及注意事项
  • form-create-designer中$inject参数的数据结构及各项属性说明
  • 软考中级软件设计师——计算机网络 IP地址与子网掩码相关题型
  • Index-AniSora模型论文速读:基于人工反馈的动漫视频生成
  • 游戏引擎学习第299天:改进排序键 第二部分
  • 小白的进阶之路系列之二----人工智能从初步到精通pytorch中分类神经网络问题详解
  • Linux 的 TCP 网络编程 -- 回显服务器,翻译服务器
  • Pandas:Series和DataFrame的概念、常用属性和方法
  • Wan2.1 文生视频 支持批量生成、参数化配置和多语言提示词管理
  • matlab慕课学习3.5
  • 《决策科学与艺术》No1: 决策树:概念、原理、发展历史、特点及应用
  • 打造高效数据处理利器:用Python实现Excel文件智能合并工具