简体   繁体   English

SynchronizationContext Send()应该是同一个线程吗?

[英]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线程上执行SendPost

From MSDN ; 来自MSDN ;

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.
     }         
}

Further Reading 进一步阅读

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并使用SendPost与同步委托调用完全相同,就像您自己完成一样。 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.

相关问题 我可以使用SynchronizationContext将工作发布或发送到当前正在运行消息泵的线程吗? - Can I use a SynchronizationContext to post or send work to a thread currently running a message pump? 从给定的线程获取SynchronizationContext - Get SynchronizationContext from a given Thread 是否可以返回带有同步上下文.send的值 - is it possible to return a value with synchronizationcontext .send SynchronizationContext.Send和SynchronizationContext.Post有什么区别? - What is the difference between SynchronizationContext.Send and SynchronizationContext.Post? 强制 SynchronizationContext 发布到控制台应用程序中的主线程 - Force SynchronizationContext to post to main thread in console app 获取TaskScheduler / SynchronizationContext以在特定线程上执行 - Getting a TaskScheduler/SynchronizationContext to execute on a specific thread 如何附加非UI线程的SynchronizationContext - How to attach SynchronizationContext of Non-UI thread 通过SynchronizationContext将超链接从其他线程添加到TextBlock - Add Hyperlink to TextBlock from other Thread by SynchronizationContext SynchronizationContext选择的线程中处于IAsyncStateMachine之外的状态是什么? - What state is in the thread that the SynchronizationContext chooses that is not in the IAsyncStateMachine? 从库中捕获主线程SynchronizationContext或Dispatcher - Capturing the main thread SynchronizationContext or Dispatcher from a library
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM