C# SynchronizationContext和Invokererequired

C# SynchronizationContext和Invokererequired,c#,winforms,multithreading,invokerequired,synchronizationcontext,C#,Winforms,Multithreading,Invokerequired,Synchronizationcontext,我一直在寻找这个问题的答案,但似乎找不到满意的答案。也许这里有人能启发我 我有一个BindingList的后代,它存储对SynchronizationContext对象的引用,以便在UI线程上引发其已更改的事件 现在,这个BindingList也可能是在UI线程而不是后台线程上创建和使用的。如果没有像invokererequired这样的属性可供我使用,我如何检查这一点?在UI线程上调用SynchronizationContext.Send的结果是什么?在SynchronizationConte

我一直在寻找这个问题的答案,但似乎找不到满意的答案。也许这里有人能启发我

我有一个
BindingList
的后代,它存储对
SynchronizationContext
对象的引用,以便在UI线程上引发其已更改的事件


现在,这个
BindingList
也可能是在UI线程而不是后台线程上创建和使用的。如果没有像
invokererequired
这样的属性可供我使用,我如何检查这一点?在UI线程上调用
SynchronizationContext.Send
的结果是什么?

SynchronizationContext
上的Send方法将同步执行,并在绑定了
SynchronizationContext
的线程上调用委托。如果同步上下文绑定到UI线程,并且代码当前正在UI线程上执行,那么委托将直接被调用,而不需要在线程之间封送。

send方法将在UI线程上同步执行,这是正确的。 然而,需要担心的一个可能结果是,调用Send将增加调用堆栈

例如,下面的代码:

for (int i = 0; i < 10000000; i++) syncContext.Send(....);
for(int i=0;i<10000000;i++)syncContext.Send(…);
将导致堆栈溢出异常。。。 这就是为什么如果您已经在所需线程上运行,那么最好避免使用同步上下文。
除了做一些内部簿记外,我不知道有什么完整的方法可以检查创建列表的线程。

你最好检查一下。在工作线程上创建绑定列表时,SynchronizationContext.Current将为null。否则,Send()会立即在UI线程上执行。我将SynchronizationContext传递给列表,因为它绑定到UI。当我引发ListChanged事件时,我会在使用它之前检查是否有SynchronizationContext。它肯定不会!首先,堆栈是每个线程分配的结构。send所做的只是发布委托,然后等待其完成。它通过互斥来实现这一点。您发布的循环不会使工作线程或UI线程的堆栈增量超过1(在工作线程上发送,在UI线程上调用委托)。如果
SynchronizationContext
足够智能,那么从UI线程调用只会将一个帧推送到堆栈中。换句话说,这里不会发生递归。