SynchronizationContext是在.NET 2.0引入的一个线程方面的一个类,在Msdn上的文档非常少也没有介绍如何使用它,mikeperetz在codeproject上写了三篇非常详细的文章来说明 第一篇文章主要介绍了如何使用这个类,参看http://www.codeproject.com/KB/threads/SynchronizationContext.aspx 第二篇文章作者介绍了如何创建一个自定义的 SynchronizationContext,用了一个将.NET线程封送到STA线程的SynchronizationContext,参看http://www.codeproject.com/KB/threads /SynchronizationContext2.aspx 第三篇文章作者讨论了如何在WCF中应用SynchronizationContext,参看http://www.codeproject.com/ KB/threads/SynchronizationContext3.aspx 中文的可以看Kevin-moon写的: 线程之间的通讯---SynchronizationContext http:/
而 SynchronizationContext 又是在 EventAggregator 中赋值: private readonly SynchronizationContext syncContext 不是每一个线程都有一个 SynchronizationContext 对象。一个总是有 SynchronizationContext 对象的是UI线程。 解决方案 现在我们知道问题原因了,解决方案也很简单,只要自定义一个 EventAggregator,源码全部照抄,但是把这句: private readonly SynchronizationContext syncContext = SynchronizationContext.Current; 替换成这句: private readonly SynchronizationContext syncContext = new SynchronizationContext(); 就不会出现 PubSubEvent 中 SynchronizationContext 等于 null 的情况了。
synchronizationContext = SynchronizationContext.Current; if (synchronizationContext ! _synchronizationContext; try { stateMachine.MoveNext();//状态机执行代码 } finally { SynchronizationContext synchronizationContext2 = synchronizationContext; Thread thread2 = thread; if (synchronizationContext2 _synchronizationContext = synchronizationContext2; } ExecutionContext executionContext3 = 的介绍,有兴趣的朋友可以去阅读以下,以下是各个.NET框架使用的SynchronizationContext: SynchronizationContext 默认 WindowsFormsSynchronizationContext
,service操作的执行将在该SynchronizationContext下执行(也就将service操作包装成delegate传入SynchronizationContext的Send或者Post方法 );同理,对于Duplex同行方式来讲,在client调用service之前,如果设置了当前线程的SynchronizationContext,callback操作也将自动在该SynchronizationContext = SynchronizationContext.Current; 22: this. 为service的执行设置LisBox和SynchronizationContext ,最后将servicehost打开。 UseSynchronizationContext实际上代表的是是否使用预设的SynchronizationContext(实际上是DispatchRuntime的SynchronizationContext
你可能从来没有使用过SynchronizationContext,但是在基于Task的异步编程中,它却总是默默存在。今天我们就来认识一下这个SynchronizationContext对象。 我们可以按照如下的方式利用SynchronizationContext来解决这个问题。 虽然被命名为SynchronizationContext,并且很多场景下我们利用该对象旨在异步线程中同步执行部分操作的问题(比如上面这个例子),但原则上可以利用自定义的SynchronizationContext 三、ConfiguredTaskAwaitable方法 我知道很少人会显式地使用SynchronizationContext上下文,但是正如我前面所说,在基于Task的异步编程中,SynchronizationContext 四、再次回到开篇的例子 由于SynchronizationContext的存在,所以如果将开篇的例子修改成如下的形式是OK的,因为await之后的操作会通过SynchronizationContext分发到
在继承了SynchronizationContext类,可以重写两个主要的方法,就是 Post 和 Send 方法。 可以通过 SynchronizationContext 的一个静态方法设置线程静态字段 var synchronizationContext = new SycnContext( ); SynchronizationContext.SetSynchronizationContext(synchronizationContext); _synchronizationContext; 小伙伴都用过 Thread.CurrentThread 这个静态属性,这个属性返回的就是当前线程,也就是不同的线程拿到的对象是不同的。 = new SycnContext(); SynchronizationContext.SetSynchronizationContext(synchronizationContext
SynchronizationContext 我在异步编程(一)这边文章里,有讲到SynchronizationContext这个类,它是.NET框架提供的类,可以在特定类型的线程中运行代码。 SynchronizationContext的实例本身并没有特殊的地方,其实例指向的是其子类,具有静态成员,可以用于读取和控制当前的SynchronizationContext。 当前SynchronizationContext是当前线程的属性。 在一个特定线程所运行到的任意的地方,都能够获取当前的SynchronizationContext并存储它,并且可以使用SynchronizationContext,在所启动的这个特定线程上运行代码。 SynchronizationContext的重要方法是POST,它可以使委托在正确的上下文中运行。 某些SynchronizationContext封装单个线程,如UI线程。
SynchronizationContext的意义 先看下MSDN中关于SynchronizationContext的定义: 提供在各种同步模型中传播同步上下文的基本功能。 此时就需要捕获UI线程的SynchronizationContext,并将这个对象传入异步任务。 中执行后继代码;false 不再尝试在捕获的线程SynchronizationContext中执行后继代码。 归根到底,这两种解决死锁的方式都是针对SynchronizationContext; ASP. NET Core和控制台程序,因为捕获的SynchronizationContext=null, 会选择一个线程同步上下文来执行,不会死锁。
SynchronizationContext 上面讲的ExecutionContext可以叫是线程环境上下文,SynchronizationContext提供在各种同步模型中传播同步上下文的基本功能 如果我们在线程中获取SynchronizationContext.Current的时候为空,null,我们可以创建一个SynchronizationContext的变量,var context=new SynchronizationContext();然后调用SynchronizationContext.SetSynchronizationContext(context);为当前线程设置同步上下文,需要在其他线程同步的时候 此外,在CS程序中,winform,wpf都由针对SynchronizationContext类重写以便实现框架层面的需要,因为在cs程序中,所有控件的创建修改删除,等操作,都应该是由UI线程去完成,如果跨线程则会报错 ; TextBox = new TextBox(); var b = SynchronizationContext.Current;
和SynchronizationContext一样,TaskScheduler也有一个Current属性,会返回当前调度程序。 控制台默认的当前线程同步上下文为null,如果给当前线程设置默认的同步上下文SynchronizationContext.SetSynchronizationContext(new SynchronizationContext 可以给他们设置默认的同步上下文SynchronizationContext。 SynchronizationContext.SetSynchronizationContext(new SynchronizationContext()); SynchronizationContext = SynchronizationContext.Current ??
服务端队列监控:队列显示瞬间增加很多任务 磁盘IO和CPU都有上升 线程dump情况,通信线程调用到了SynchronizationContext,底层的work通信线程怎么调用到了获取节点的业务方法去了 三、问题根因 RPC框架中代码中有使用SynchronizationContext,此处与gRPC共用。 SynchronizationContext使用的queue是ConcurrentLinkedQueue队列,被单线程串行执行。 问题原因:再回到上面的线程栈,业务节点发现事件和gRPC底层通信共用了SynchronizationContext造成阻塞,和线程错乱执行。 问题解决:不再和gRPC共用SynchronizationContext,如果使用单独实例化一个即可。该问题通过测试同学通过故障注入的方式得以复现。
在DispatchRuntime初始化过程中,会按照如下所示的伪代码对SynchronizationContext进行初始化。 如果不满足上面的条件,则将当前线程的同步上下文赋值给SynchronizationContext属性。 具体来讲,如果UseSynchronizationContext属性为False,会将SynchronizationContext设置为NULL。 因此,在DispatchRuntime的SynchronizationContext存在的情况下,后续的消息处理过程都是以同步的方式执行的。 context = dispatchRuntime.SynchronizationContext; 6: if (context !
(continueOnCapturedContext:false) 如果存在 SynchronizationContext,回调会优先在 SynchronizationContext 上执行。 下面是一个 SynchronizationContext 的实现示例: class SingleThreadedSynchronizationContext : SynchronizationContext ().GetResult(); Console.WriteLine($"Test.SynchronizationContext2: {SynchronizationContext.Current ().GetResult(); Console.WriteLine($"Test.SynchronizationContext2: {SynchronizationContext.Current 了 Console.WriteLine($"DoSthAsync.SynchronizationContext2: {SynchronizationContext.Current}")
_executionContext; ExecutionContext executionContext2 = executionContext; SynchronizationContext synchronizationContext _synchronizationContext; try { stateMachine.MoveNext(); } finally { SynchronizationContext synchronizationContext2 = synchronizationContext; Thread thread2 = thread; if (synchronizationContext2 ! _synchronizationContext) { thread2. _synchronizationContext = synchronizationContext2; } ExecutionContext executionContext3 = executionContext2
“Is the class where the usage context is within the task libraries. “ 它的作用像是WPF/Winform时代的SynchronizationContext 像SynchronizationContext.一样,TaskScheduler也有可能依赖特定的UI SynchronizationContext.
这是可以封装一个异步的数据集合: public class AsyncObservableCollection<T> : ObservableCollection<T> { //获取当前线程的SynchronizationContext 对象 private SynchronizationContext _synchronizationContext = SynchronizationContext.Current; public == _synchronizationContext) { //如果操作发生在同一个线程中,不需要进行跨线程执行 RaiseCollectionChanged { //如果不是发生在同一个线程中 //准确说来,这里是在一个非UI线程中,需要进行UI的更新所进行的操作 _synchronizationContext.Post == _synchronizationContext) { // Execute the PropertyChanged event on the current
因为 Task 调度回到线程上下文靠的是 SynchronizationContext,WPF UI 线程的 SynchronizationContext 被设置为了 DispatcherSynchronizationContext 希望了解 Dispatcher 和 SynchronizationContext 的区别可以阅读 c# - Difference between Synchronization Context and DispatcherSynchronizationContext 执行 await 后续任务的上下文代码:
///
= sc }; 7 } SynchronizationContext.CurrentNoFlow作用是取得当前线程的SynchronizationContext,这个有什么用呢,SynchronizationContext ,系统会给主线程添加SynchronizationContext,也就是SynchronizationContext.Current = new WinFormSynchronizationContext 10 { 11 var syncCtx = SynchronizationContext.CurrentNoFlow; //获取当前SynchronizationContext = typeof(SynchronizationContext)) //当前SynchronizationContext和传进来的SynchronizationContext不相等 13 (true)-(默认),则会在异步操作前Capture当前线程的SynchronizationContext,异步操作之后运行MoveNext时通过SynchronizationContext转到目标之前的线程
/ 12 public class HttpHelper 13 { 14 private string postData; 15 SynchronizationContext param name="data"></param> 37 /// <param name="mediaType"></param> 38 /// <param name="<em>synchronizationContext</em> param name="callBack"></param> 40 public void Post(string url, string data, string mediaType, SynchronizationContext synchronizationContext, SendOrPostCallback callBack) 41 { 42 currentContext = synchronizationContext namespace SLAwb 9 { 10 public partial class MainPage : UserControl 11 { 12 private SynchronizationContext
解决方案 ThreadPool.QueueUserWorkItem(delegate { SynchronizationContext.SetSynchronizationContext DispatcherSynchronizationContext(System.Windows.Application.Current.Dispatcher)); SynchronizationContext.Current.Post