<commit_before>namespace System.Threading
{
    using System.Collections.Concurrent;
    using System.Diagnostics;

    [DebuggerStepThrough]
    sealed class UISynchronizationContext : SynchronizationContext, IDisposable
    {
        struct WorkItem
        {
            public SendOrPostCallback callback;
            public object state;
            public AutoResetEvent handle;
        }

        public static UISynchronizationContext BindToCurrent()
        {
            var result = new UISynchronizationContext();
            SetSynchronizationContext(result);
            return result;
        }

        private bool disposed;
        private Thread uiThread;
        private SynchronizationContext previous = Current;
        private readonly BlockingCollection<WorkItem> workItems = new BlockingCollection<WorkItem>();
        
        private void EnsureUIThread()
        {
            if (uiThread == null)
            {
                lock (workItems)
                {
                    if (uiThread == null)
                    {
                        uiThread = new Thread(Loop) { Name = "UIThread" };
                        uiThread.Start();
                    }
                }
            }
        }

        private void Loop(object obj)
        {
            SetSynchronizationContext(this);

            while (!disposed)
            {
                var currentItem = workItems.Take();
                currentItem.callback(currentItem.state);
                if (currentItem.handle != null)
                {
                    currentItem.handle.Set();
                }
            }
        }

        public override void Post(SendOrPostCallback d, object state)
        {
            if (Thread.CurrentThread == uiThread)
            {
                d(state);
            }
            else
            {
                EnsureUIThread();
                workItems.Add(new WorkItem { callback = d, state = state });
            }
        }

        public override void Send(SendOrPostCallback d, object state)
        {
            if (Thread.CurrentThread == uiThread)
            {
                d(state);
            }
            else
            {
                EnsureUIThread();
                var workItem = new WorkItem { callback = d, state = state, handle = new AutoResetEvent(false) };
                workItems.Add(workItem);
                workItem.handle.WaitOne();
            }
        }

        public void Dispose()
        {
            disposed = true;
            workItems.Dispose();
            SetSynchronizationContext(previous);
        }
    }
}<commit_msg>Fix AppDomainUnloadedException caused by work scheduled to UISynchronizationContext been executed after shutdown of the test AppDomain<commit_after>namespace System.Threading
{
    using System.Collections.Concurrent;
    using System.Diagnostics;

    [DebuggerStepThrough]
    class UISynchronizationContext : SynchronizationContext, IDisposable
    {
        struct WorkItem
        {
            public SendOrPostCallback callback;
            public object state;
            public AutoResetEvent handle;
        }

        public static UISynchronizationContext BindToCurrent()
        {
            var result = new UISynchronizationContext();
            SetSynchronizationContext(result);
            return result;
        }

        private bool disposed;
        private Thread uiThread;
        private SynchronizationContext previous = SynchronizationContext.Current;
        private readonly BlockingCollection<WorkItem> workItems = new BlockingCollection<WorkItem>();

        private void EnsureUIThread()
        {
            if (uiThread == null)
            {
                lock (workItems)
                {
                    if (uiThread == null)
                    {
                        uiThread = new Thread(Loop) { Name = "UIThread" };
                        uiThread.Start();
                    }
                }
            }
        }

        private void Loop(object obj)
        {
            SetSynchronizationContext(this);

            while (!disposed)
            {
                var currentItem = workItems.Take();

                try
                {
                    currentItem.callback(currentItem.state);
                }
                catch (Exception e)
                {
                    Debug.WriteLine(e);
                }
                finally
                {
                    if (currentItem.handle != null)
                    {
                        currentItem.handle.Set();
                    }
                }
            }
        }

        public override void Post(SendOrPostCallback d, object state)
        {
            EnsureUIThread();
            workItems.Add(new WorkItem { callback = d, state = state });
        }

        public override void Send(SendOrPostCallback d, object state)
        {
            if (Thread.CurrentThread == uiThread)
            {
                d(state);
            }
            else
            {
                EnsureUIThread();
                var workItem = new WorkItem { callback = d, state = state, handle = new AutoResetEvent(false) };
                workItems.Add(workItem);
                workItem.handle.WaitOne();
            }
        }

        public void Dispose()
        {
            disposed = true;
            SetSynchronizationContext(previous);
        }
    }
}
{'fraction_non_alphanumeric': 0.07072368421052631, 'fraction_numerical': 0.0, 'mean_word_length': 1.2513368983957218, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7473362', 'n_tokens_mistral': 1297, 'n_tokens_neox': 1219, 'n_words': 282}