寻找一个自定义的SynchronizationContext的例子(用于单元测试)自定义、单元测试、例子、SynchronizationContext

2023-09-02 21:43:46 作者:沧海佚夫

我需要一个自定义的SynchronizationContext即:

I need a custom SynchronizationContext that:

旗下拥有运行上岗和一个单独的线程发送代表 是否发送在它们发送的顺序 在不需要任何其他的方法

我需要这个,所以我可以单元测试一些线程code,它会跟WinForm的在实际应用。

I need this so I can unit test some threading code that will talk to WinForm in the real application.

在我写我自己,我希望有人可以点我到一个简单的(小)的实现。

Before I write my own, I was hoping that someone could point me to a simple (and small) implementations.

推荐答案

这本是前一段时间我写的,有版权的任何问题,也无法保证(系统没有投入生产):

This one was written by me some time ago, no issues with copyright, no guarantees either(the system didn't go into production):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Threading;

namespace ManagedHelpers.Threads
{
    public class STASynchronizationContext : SynchronizationContext, IDisposable
    {
        private readonly Dispatcher dispatcher;
        private object dispObj;
        private readonly Thread mainThread;

        public STASynchronizationContext()
        {
            mainThread = new Thread(MainThread) { Name = "STASynchronizationContextMainThread", IsBackground = false };
            mainThread.SetApartmentState(ApartmentState.STA);
            mainThread.Start();

            //wait to get the main thread's dispatcher
            while (Thread.VolatileRead(ref dispObj) == null)
                Thread.Yield();

            dispatcher = dispObj as Dispatcher;
        }

        public override void Post(SendOrPostCallback d, object state)
        {
            dispatcher.BeginInvoke(d, new object[] { state });
        }

        public override void Send(SendOrPostCallback d, object state)
        {
            dispatcher.Invoke(d, new object[] { state });
        }

        private void MainThread(object param)
        {
            Thread.VolatileWrite(ref dispObj, Dispatcher.CurrentDispatcher);
            Console.WriteLine("Main Thread is setup ! Id = {0}", Thread.CurrentThread.ManagedThreadId);
            Dispatcher.Run();
        }

        public void Dispose()
        {
            if (!dispatcher.HasShutdownStarted && !dispatcher.HasShutdownFinished)
                dispatcher.BeginInvokeShutdown(DispatcherPriority.Normal);

            GC.SuppressFinalize(this);
        }

        ~STASynchronizationContext()
        {
            Dispose();
        }
    }
}