Note that there are some explanatory texts on larger screens.

plurals
  1. POComparing SynchronizationContext
    primarykey
    data
    text
    <p>How do I compare SynchronizationContext? It seems that the same Dispatcher can create different SynchronizationContext when using BeginInvoke. When I drill down into the two (unequal) contexts, I see that the dispatcher Thread ID is the same, yet they are not Equal to each other.</p> <pre><code>public partial class MainWindow : Window { private SynchronizationContext contexta; private SynchronizationContext contextb; private SynchronizationContext contextc; private SynchronizationContext contextd; public MainWindow() { InitializeComponent(); contexta = SynchronizationContext.Current; Loaded += MainWindow_Loaded; } private void MainWindow_Loaded(object sender, RoutedEventArgs e) { contextb = SynchronizationContext.Current; Dispatcher.Invoke(() =&gt; { contextc = SynchronizationContext.Current; }); Dispatcher.BeginInvoke(new Action(() =&gt; { contextd = SynchronizationContext.Current; })); Debug.Assert(contexta != contextb); Debug.Assert(contexta == contextc); // fails... why?!?!? Debug.Assert(contexta == contextd); // fails... why?!?!? Debug.Assert(contextc == contextd); // fails... why?!?!? } </code></pre> <p>Maybe the two of them cannot be used together. I noticed that this actually works:</p> <pre><code> contexta.Send(new SendOrPostCallback((s) =&gt; { contexte = SynchronizationContext.Current; }), null); </code></pre> <p><strong>Update</strong> But strangely, it doesn't always work. </p> <pre><code> public override void AddRange(IEnumerable&lt;T&gt; items) { if (SynchronizationContext.Current == _context) { base.AddRange(items); } else { _context.Send(new SendOrPostCallback((state) =&gt; { AddRange(state as IEnumerable&lt;T&gt;); }), items); } } </code></pre> <p>never gets a matched _context and goes on forever, for example. Even though it shouldn't. This latter example the threads actually end up being the same, and there is a context, but it is different.</p> <p><strong>Update2</strong> Ok, I got it to work, but I really feel uncomfortable about it. Apparently, when you Post or Send, your task is run from the right thread, but if you aren't coming from the UI, it seems that a new SynchronizationContext is generated.</p> <pre><code> public override void AddRange(IEnumerable&lt;T&gt; items) { if (SynchronizationContext.Current == _context) { base.AddRange(items); } else { _context.Post(new SendOrPostCallback((state) =&gt; { if (SynchronizationContext.Current != _context) SynchronizationContext.SetSynchronizationContext(_context); // called every time.. strange AddRange(items); }), null); } } </code></pre> <p>And look at this:</p> <p><img src="https://i.stack.imgur.com/hWxBN.png" alt="enter image description here"></p> <p>"Requires full trust for the immediate caller. This member cannot be used by partially trusted or transparent code." :(</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload