[英]SynchronizationContext Send() supposed to be the same thread?
I have this scenario where I try to handle an event on the same thread as it was created. 我有这种情况,我尝试在创建的同一个线程上处理事件。 Which is commonly done in the UiThread, but I'm not on the UiThread to start with.
这通常在UiThread中完成,但我不是在UiThread上开始。 I have some test with basically the following steps.
我有一些测试基本上有以下步骤。 I have left out some details.
我遗漏了一些细节。 I am not really sure whether or not this should act as I think it should .
我不确定这是否应该按照我认为的那样行事。
First I check the Id of the current thread 首先,我检查当前线程的Id
var myThreadId = Thread.CurrentThread.ManagedThreadId;
I create a SynchronizationContext and set is as current 我创建了一个SynchronizationContext,并设置为当前
var _context = new SynchronizationContext();
SynchronizationContext.SetSynchronizationContext(_context);
Then I send some action to the context (We are now on another thread) 然后我发送一些动作到上下文(我们现在在另一个线程)
_context.Send(x => _action(sender, e), null);
Inside this action, I check the ThreadId again 在这个动作中,我再次检查ThreadId
Assert.Equal(myThreadId, Thread.CurrentThread.ManagedThreadId);
This fails. 这失败了。 Am I not supposed to be on my original thread again?
我不应该再次使用原始帖子吗?
If you create a new SynchronizationContext
, it will always wrap the Thread Pool and never execute Send
or Post
on the UI thread. 如果您创建一个新的
SynchronizationContext
,它将始终包装线程池,并且永远不会在UI线程上执行Send
或Post
。
The SynchronizationContext class is a base class that provides a free-threaded context with no synchronization.
SynchronizationContext类是一个基类,它提供没有同步的自由线程上下文。
For example; 例如;
void Button_Click(object sender, EventArgs e)
{
var context = SynchronizationContext.Current;
// this is executred on the UI thread.
context.Send(() =>
{
// this is also executed on the UI thread.
});
Task.Run(() =>
{
// this is executed on a worker thread
context.Send(() =>
{
// this is still executed on the UI thread!
});
}
// what you are doing will always execute on a worker thread.
var myNewContext = new SynchronizationContext();
SynchronizationContext.SetSynchronizationContext(myNewContext);
myNewContext.Send(() =>
{
// this will run on a worker thread.
}
}
Parallel Computing - It's All About the SynchronizationContext 并行计算 - 它是关于SynchronizationContext的全部
Creating a new SynchronizationContext
and using Send
or Post
is exactly the same as a synchronous delegate invocation as if you'd do it yourself. 创建新的
SynchronizationContext
并使用Send
或Post
与同步委托调用完全相同,就像您自己完成一样。 The code is rather simple (taken from the source ): 代码相当简单(取自源代码 ):
public virtual void Send(SendOrPostCallback d, Object state)
{
d(state);
}
You're trying to mimic the operation of custom contexts, such as the DispatcherSynchronizationContext
for example, which is aware of the WPF's UI message loop thread. 您正试图模仿自定义上下文的操作,例如
DispatcherSynchronizationContext
,它知道WPF的UI消息循环线程。 That behavior does not happen here. 这种行为不会发生在这里。
If you're coming from the UI thread, you'll need to capture the context and pass it along. 如果您来自UI线程,则需要捕获上下文并将其传递。
You can see this more clearly inside the DispatcherSynchronizationContext
which queues work to the UI using the Dispatcher
class: 您可以在
DispatcherSynchronizationContext
更清楚地看到这一点,使用Dispatcher
类将队列工作到UI:
/// <summary>
/// Synchronously invoke the callback in the SynchronizationContext.
/// </summary>
public override void Send(SendOrPostCallback d, Object state)
{
// Call the Invoke overload that preserves the behavior of passing
// exceptions to Dispatcher.UnhandledException.
if(BaseCompatibilityPreferences.GetInlineDispatcherSynchronizationContextSend() &&
_dispatcher.CheckAccess())
{
// Same-thread, use send priority to avoid any reentrancy.
_dispatcher.Invoke(DispatcherPriority.Send, d, state);
}
else
{
// Cross-thread, use the cached priority.
_dispatcher.Invoke(_priority, d, state);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.