<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>jaredpar's WebLog : SynchronizationContext</title><link>http://blogs.msdn.com/jaredpar/archive/tags/SynchronizationContext/default.aspx</link><description>Tags: SynchronizationContext</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Simple class for tests involving a SynchronizationContext</title><link>http://blogs.msdn.com/jaredpar/archive/2008/08/25/simple-class-for-tests-involving-a-synchronizationcontext.aspx</link><pubDate>Mon, 25 Aug 2008 15:00:34 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8889917</guid><dc:creator>Jared Parsons</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/jaredpar/comments/8889917.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jaredpar/commentrss.aspx?PostID=8889917</wfw:commentRss><wfw:comment>http://blogs.msdn.com/jaredpar/rsscomments.aspx?PostID=8889917</wfw:comment><description>&lt;p&gt;Recently I had to test a class which heavily depended upon a &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx"&gt;SynchronizationContext&lt;/a&gt;.&amp;#160; This threw me off for about half an hour as I didn't want to write multi-threaded unit tests.&amp;#160; Multi-threaded code is difficult enough without adding needless threads.&amp;#160; &lt;/p&gt;  &lt;p&gt;The solution I came up with is simple and gives the unit test a large degree of control over the execution of posted delegates.&amp;#160; The resulting tests were much easier to code and understand. &lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public sealed class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;TestSynchronizationContext &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;SynchronizationContext &lt;/span&gt;{
    &lt;span style="color: blue"&gt;private &lt;/span&gt;&lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Tuple&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;SendOrPostCallback&lt;/span&gt;, &lt;span style="color: blue"&gt;object&lt;/span&gt;&amp;gt;&amp;gt; m_pending 
        = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Tuple&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;SendOrPostCallback&lt;/span&gt;, &lt;span style="color: blue"&gt;object&lt;/span&gt;&amp;gt;&amp;gt;();

    &lt;span style="color: blue"&gt;public override void &lt;/span&gt;Send(&lt;span style="color: #2b91af"&gt;SendOrPostCallback &lt;/span&gt;d, &lt;span style="color: blue"&gt;object &lt;/span&gt;state) {
        d(state);
    }

    &lt;span style="color: blue"&gt;public override void &lt;/span&gt;Post(&lt;span style="color: #2b91af"&gt;SendOrPostCallback &lt;/span&gt;d, &lt;span style="color: blue"&gt;object &lt;/span&gt;state) {
        m_pending.Add(&lt;span style="color: #2b91af"&gt;Tuple&lt;/span&gt;.Create(d, state));
    }

    &lt;span style="color: blue"&gt;public void &lt;/span&gt;RunAllPosted() {
        m_pending.ForEach(x =&amp;gt; x.First(x.Second));
    }
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8889917" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jaredpar/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Testing/default.aspx">Testing</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/SynchronizationContext/default.aspx">SynchronizationContext</category></item><item><title>SynchronizationContext and Higher Order Functions</title><link>http://blogs.msdn.com/jaredpar/archive/2008/02/24/synchronizationcontext-and-higher-order-functions.aspx</link><pubDate>Sun, 24 Feb 2008 12:42:48 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7874717</guid><dc:creator>Jared Parsons</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/jaredpar/comments/7874717.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jaredpar/commentrss.aspx?PostID=7874717</wfw:commentRss><wfw:comment>http://blogs.msdn.com/jaredpar/rsscomments.aspx?PostID=7874717</wfw:comment><description>&lt;p&gt;It's often useful to ensure that actions occur on specific threads, in particular event handlers.&amp;#160; Take Windows Forms for instance where all operations on a Control must occur on the thread it was created on.&amp;#160; Typically this is not a problem since WinForms respond to events such as Click, Move, etc...&amp;#160; These events are sourced from the same thread so it's not an issue.&amp;#160; &lt;/p&gt;  &lt;p&gt;But there are cases where events are sourced from a separate thread and we need to Marshal it back onto the Control thread.&amp;#160; One good example of this is &lt;a href="http://msdn2.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx"&gt;FileSystemWatcher&lt;/a&gt;.&amp;#160; If a SynchronizationObject is not provided it will raise the event on an unspecified thread.&amp;#160; This event cannot directly touch a Control or an &amp;quot;Illegal cross thread call exception&amp;quot; will occur.&amp;#160; Many examples use ISynchronizedInvoke to marshal the code back.&amp;#160; There are a couple of downsides to this approach including&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;ISynchronizedInvoke on Controls won't work until the Handle is created or after it's destroyed.&amp;#160; So if the event fires in either of these cases an unhandled exception will occur and typically crash the process. &lt;/li&gt;    &lt;li&gt;Can't use an anonymous lambda because ISynchronizedInvoke is not typed to a specific delegate &lt;/li&gt;    &lt;li&gt;Code is easy to get subtly wrong &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Here is an example implementation.&amp;#160; &lt;/p&gt;  &lt;pre class="code"&gt;        &lt;span style="color: rgb(0,0,255)"&gt;private&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; OnFileChanged(&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt; sender, &lt;span style="color: rgb(43,145,175)"&gt;FileSystemEventArgs&lt;/span&gt; e)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;if&lt;/span&gt;( &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.InvokeRequired )
            {
                &lt;span style="color: rgb(0,128,0)"&gt;// If the handle is not created this will throw
&lt;/span&gt;                Invoke((&lt;span style="color: rgb(43,145,175)"&gt;MethodInvoker&lt;/span&gt;)(() =&amp;gt; OnFileChanged(sender, e)));
                &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt;;
            }

            textBox2.Text = &lt;span style="color: rgb(43,145,175)"&gt;String&lt;/span&gt;.Format(&lt;span style="color: rgb(163,21,21)"&gt;&amp;quot;{0} {1}&amp;quot;&lt;/span&gt;, e.ChangeType, e.Name);
        }&lt;/pre&gt;

&lt;p&gt;It would be easier if we could bind a delegate to a particular thread in such way that calls automatically marshal to the appropriate thread.&amp;#160; Imagine for instance if we could type the following in such a way that all invocations of &amp;quot;del&amp;quot; below would automatically marshal to the thread for the Control.&amp;#160; We could then freely pass this to any event source and not have to worry about what thread the event is raised on.&amp;#160; &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; del = &lt;span style="color: rgb(43,145,175)"&gt;SynchronizationContext&lt;/span&gt;.Current.BindDelegateAsPost(&lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;FileSystemEventHandler&lt;/span&gt;(OnFileChanged));&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Instead of ISynchronizedInvoke we'll use &lt;a href="http://msdn2.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx"&gt;SynchronizationContext&lt;/a&gt;.&amp;#160; IMHO this is a better approach for this type of work.&amp;#160; It has the same functionality as ISynchronizedInvoke and helps with a few of the quirks.&amp;#160; The Windows Forms Application Model (and if memory serves WPF) insert a &lt;a href="http://msdn2.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx"&gt;SynchronizationContext&lt;/a&gt; for every thread running a WinForm application.&amp;#160; It greatly reduces the chance your code will run into problem #1 above because the timespan for when it can be used to Marshal between threads is not dependent upon the internal workings of a particular Control.&amp;#160; Instead it's tied to the lifetime of the Thread[1].&amp;#160; &lt;/p&gt;

&lt;p&gt;The basic strategy we'll take is to create a new delegate which wraps the original delegate.&amp;#160; This will Marshal the call onto the appropriate thread and then call the original delegate. &lt;a href="http://msdn2.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx"&gt;SynchronizationContext&lt;/a&gt; has two methods to Marshal calls between threads; Post and Send.&amp;#160; &lt;/p&gt;

&lt;p&gt;Creating a delegate instance on the fly is not straight forward.&amp;#160; Unless we code all permutations of delegate signatures into a class we cannot use the Delegate.Create API because we cannot provide a method with the matching signature.&amp;#160; Instead we need to go through Reflection.Emit.&amp;#160; This allows us to build a method on the fly to match the delegate signature.&amp;#160; In addition we can generate the IL to route the code through Post/Send before calling the delegate.&lt;/p&gt;

&lt;p&gt;First up are extension methods for &lt;a href="http://msdn2.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx"&gt;SynchronizationContext&lt;/a&gt; that call into a helper class.&lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;static&lt;/span&gt; T BindDelegateAsPost&amp;lt;T&amp;gt;(&lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;SynchronizationContext&lt;/span&gt; context, T del)
{
    &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;DelegateFactory&lt;/span&gt;.CreateAsPost(context, del);
} &lt;/pre&gt;

&lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;static&lt;/span&gt; T BindDelegateAsSend&amp;lt;T&amp;gt;(&lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;SynchronizationContext&lt;/span&gt; context, T del)
{
    &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;DelegateFactory&lt;/span&gt;.CreateAsSend(context, del);
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;Next is a class which injects the Send/Post call.&amp;#160; We need this as a storage mechanism for holding the context and delegate.&amp;#160; Essentially this is a hand generate closure.&lt;/p&gt;

&lt;pre class="code"&gt;    &lt;span style="color: rgb(0,0,255)"&gt;private&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;class&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;DelegateData
&lt;/span&gt;    {
        &lt;span style="color: rgb(0,0,255)"&gt;private&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;SynchronizationContext&lt;/span&gt; m_context;
        &lt;span style="color: rgb(0,0,255)"&gt;private&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;Delegate&lt;/span&gt; m_target;

        &lt;span style="color: rgb(0,0,255)"&gt;internal&lt;/span&gt; DelegateData(&lt;span style="color: rgb(43,145,175)"&gt;SynchronizationContext&lt;/span&gt; context, &lt;span style="color: rgb(43,145,175)"&gt;Delegate&lt;/span&gt; target)
        {
            m_target = target;
            m_context = context;
        }

        &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Send(&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt;[] args)
        {
            m_context.Send(() =&amp;gt; m_target.DynamicInvoke(args));
        }

        &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Post(&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt;[] args)
        {
            m_context.Post(() =&amp;gt; m_target.DynamicInvoke(args));
        }
    }&lt;/pre&gt;

&lt;p&gt;Now comes the actual delegate generation.&amp;#160; The dynamic method will be bound to an instance of the DelegateData class.&amp;#160; As such we must add an additional parameter to the delegate of type DelegateData in position 0.&amp;#160; The rest of the method creates an object array with length equal to the number of parameters in the delegate.&amp;#160; Each of the arguments are added to this array.&amp;#160; Then it will call Post/Send in DelegateData passing the arguments along.&amp;#160; &lt;/p&gt;

&lt;pre class="code"&gt;    &lt;span style="color: rgb(0,0,255)"&gt;private&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;static&lt;/span&gt; T Create&amp;lt;T&amp;gt;(&lt;span style="color: rgb(43,145,175)"&gt;SynchronizationContext&lt;/span&gt; context, T target, &lt;span style="color: rgb(0,0,255)"&gt;string&lt;/span&gt; name)
    {
        &lt;span style="color: rgb(43,145,175)"&gt;Delegate&lt;/span&gt; del = (&lt;span style="color: rgb(43,145,175)"&gt;Delegate&lt;/span&gt;)(&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt;)target;
        &lt;span style="color: rgb(0,0,255)"&gt;if&lt;/span&gt; (del.Method.ReturnType != &lt;span style="color: rgb(0,0,255)"&gt;typeof&lt;/span&gt;(&lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt;))
        {
            &lt;span style="color: rgb(0,0,255)"&gt;throw&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;ArgumentException&lt;/span&gt;(&lt;span style="color: rgb(163,21,21)"&gt;&amp;quot;Only void return types currently supported&amp;quot;&lt;/span&gt;);
        }

        &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; paramList = &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(43,145,175)"&gt;Type&lt;/span&gt;&amp;gt;();
        paramList.Add(&lt;span style="color: rgb(0,0,255)"&gt;typeof&lt;/span&gt;(&lt;span style="color: rgb(43,145,175)"&gt;DelegateData&lt;/span&gt;));
        paramList.AddRange(del.Method.GetParameters().Project((x) =&amp;gt; x.ParameterType));
        &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; method = &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;DynamicMethod&lt;/span&gt;(
            &lt;span style="color: rgb(163,21,21)"&gt;&amp;quot;AMethodName&amp;quot;&lt;/span&gt;,
            del.Method.ReturnType,
            paramList.ToArray(),
            &lt;span style="color: rgb(0,0,255)"&gt;typeof&lt;/span&gt;(&lt;span style="color: rgb(43,145,175)"&gt;DelegateData&lt;/span&gt;));
        &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; gen = method.GetILGenerator();
        &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; localInfo = gen.DeclareLocal(&lt;span style="color: rgb(0,0,255)"&gt;typeof&lt;/span&gt;(&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt;[]));
        gen.Emit(&lt;span style="color: rgb(43,145,175)"&gt;OpCodes&lt;/span&gt;.Ldc_I4, paramList.Count - 1);
        gen.Emit(&lt;span style="color: rgb(43,145,175)"&gt;OpCodes&lt;/span&gt;.Newarr, &lt;span style="color: rgb(0,0,255)"&gt;typeof&lt;/span&gt;(&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt;));
        gen.Emit(&lt;span style="color: rgb(43,145,175)"&gt;OpCodes&lt;/span&gt;.Stloc, localInfo.LocalIndex);
        &lt;span style="color: rgb(0,0,255)"&gt;for&lt;/span&gt; (&lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt; i = 1; i &amp;lt; paramList.Count; ++i)
        {
            gen.Emit(&lt;span style="color: rgb(43,145,175)"&gt;OpCodes&lt;/span&gt;.Ldloc, localInfo.LocalIndex);
            gen.Emit(&lt;span style="color: rgb(43,145,175)"&gt;OpCodes&lt;/span&gt;.Ldc_I4, i - 1);
            gen.Emit(&lt;span style="color: rgb(43,145,175)"&gt;OpCodes&lt;/span&gt;.Ldarg, i);
            &lt;span style="color: rgb(0,0,255)"&gt;if&lt;/span&gt; (paramList[i].IsValueType)
            {
                gen.Emit(&lt;span style="color: rgb(43,145,175)"&gt;OpCodes&lt;/span&gt;.Box);
            }
            gen.Emit(&lt;span style="color: rgb(43,145,175)"&gt;OpCodes&lt;/span&gt;.Stelem_Ref);
        }

        gen.Emit(&lt;span style="color: rgb(43,145,175)"&gt;OpCodes&lt;/span&gt;.Ldarg_0);
        gen.Emit(&lt;span style="color: rgb(43,145,175)"&gt;OpCodes&lt;/span&gt;.Ldloc, localInfo.LocalIndex);
        gen.EmitCall(&lt;span style="color: rgb(43,145,175)"&gt;OpCodes&lt;/span&gt;.Call, &lt;span style="color: rgb(0,0,255)"&gt;typeof&lt;/span&gt;(&lt;span style="color: rgb(43,145,175)"&gt;DelegateData&lt;/span&gt;).GetMethod(name, &lt;span style="color: rgb(43,145,175)"&gt;BindingFlags&lt;/span&gt;.Instance | &lt;span style="color: rgb(43,145,175)"&gt;BindingFlags&lt;/span&gt;.Public), &lt;span style="color: rgb(0,0,255)"&gt;null&lt;/span&gt;);
        gen.Emit(&lt;span style="color: rgb(43,145,175)"&gt;OpCodes&lt;/span&gt;.Ret);
        &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; (T)(&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt;)method.CreateDelegate(&lt;span style="color: rgb(0,0,255)"&gt;typeof&lt;/span&gt;(T), &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;DelegateData&lt;/span&gt;(context, del));
    }

    &lt;span style="color: rgb(0,0,255)"&gt;internal&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;static&lt;/span&gt; T CreateAsSend&amp;lt;T&amp;gt;(&lt;span style="color: rgb(43,145,175)"&gt;SynchronizationContext&lt;/span&gt; context, T target)
    {
        &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; Create(context, target, &amp;quot;Send&amp;quot;);
    }

    &lt;span style="color: rgb(0,0,255)"&gt;internal&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;static&lt;/span&gt; T CreateAsPost&amp;lt;T&amp;gt;(&lt;span style="color: rgb(43,145,175)"&gt;SynchronizationContext&lt;/span&gt; context, T target)
    {
        &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; Create(context, target, &amp;quot;Post&amp;quot;);
    }&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;The resulting delegate is now of the same type as the original delegate and invocations will occur on the targeted thread.&amp;#160; &lt;/p&gt;

&lt;p&gt;[1] Granted if you try to use a &lt;a href="http://msdn2.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx"&gt;SynchronizationContext&lt;/a&gt; to Marshal between threads after the target thread has finished you will still get an error.&amp;#160; &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7874717" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jaredpar/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Patterns/default.aspx">Patterns</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Lambda/default.aspx">Lambda</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Threading/default.aspx">Threading</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/SynchronizationContext/default.aspx">SynchronizationContext</category></item></channel></rss>