博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Marshal Code Into Another Thread(STAThread)
阅读量:6929 次
发布时间:2019-06-27

本文共 8958 字,大约阅读时间需要 29 分钟。

出处:

MSND解释:

SynchronizationContext 类是一个基类,可提供不带同步的自由线程上下文。此类实现的同步模型的目的是使公共语言运行时内部的异步/同步操作能够针对不同的异步模型采取正确的行为。此模型还简化了托管应用程序为在不同的同步环境下正常工作而必须遵循的一些要求。同步模型的提供程序可以扩展此类并为这些方法提供自己的实现。 

一个我们所熟悉的t它提供了将操作“封送”到UI线程的能力,而文章中演示了如何通过自己实现的SynchronizationContext将方法“封送”(Marshal)到STA线程上执行,并自己实现了STA线程模型。对了解多线程同步、SynchronizationContext和STA线程模型很有帮助值得学习。

BlockingQueue
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace SynchronizationContextDemo{    internal interface IQueueReader
: IDisposable { T Dequeue(); void ReleaseReader(); } internal interface IQueueWriter
: IDisposable { void Enqueue(T data); } internal class BlockingQueue
: IQueueReader
, IQueueWriter
, IDisposable { // use a .NET queue to store the data private Queue
mQueue = new Queue
(); // create a semaphore that contains the items in the queue as resources. // initialize the semaphore to zero available resources (empty queue). private Semaphore mSemaphore = new Semaphore(0, int.MaxValue); // a event that gets triggered when the reader thread is exiting private ManualResetEvent mKillThread = new ManualResetEvent(false); // wait handles that are used to unblock a Dequeue operation. // Either when there is an item in the queue // or when the reader thread is exiting. private WaitHandle[] mWaitHandles; public BlockingQueue() { mWaitHandles = new WaitHandle[2] { mSemaphore, mKillThread }; } public void Enqueue(T data) { lock (mQueue) { mQueue.Enqueue(data); //mQueue.Enqueue(data);//test } // add an available resource to the semaphore, // because we just put an item // into the queue. mSemaphore.Release(); //mSemaphore.Release(2);//test } public T Dequeue() { // wait until there is an item in the queue WaitHandle.WaitAny(mWaitHandles); lock (mQueue) { if (mQueue.Count > 0) return mQueue.Dequeue(); } return default(T); } public void ReleaseReader() { mKillThread.Set(); } void IDisposable.Dispose() { if (mSemaphore != null) { mSemaphore.Close(); mQueue.Clear(); mSemaphore = null; } } }}
SendOrPostCallbackItem
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace SynchronizationContextDemo{    internal enum ExecutionType    {        Post,        Send    }    internal class SendOrPostCallbackItem    {        object mState;        private ExecutionType mExeType;        SendOrPostCallback mMethod;        ManualResetEvent mAsyncWaitHandle = new ManualResetEvent(false);        Exception mException = null;        internal SendOrPostCallbackItem(SendOrPostCallback callback,           object state, ExecutionType type)        {            mMethod = callback;            mState = state;            mExeType = type;        }        internal Exception Exception        {            get { return mException; }        }        internal bool ExecutedWithException        {            get { return mException != null; }        }        // this code must run ont the STA thread        internal void Execute()        {            if (mExeType == ExecutionType.Send)                Send();            else                Post();        }        // calling thread will block until mAsyncWaitHandle is set        internal void Send()        {            try            {                // call the thread                mMethod(mState);            }            catch (Exception e)            {                mException = e;            }            finally            {                mAsyncWaitHandle.Set();            }        }        ///         /// Unhandled exceptions will terminate the STA thread        ///         internal void Post()        {            mMethod(mState);        }        internal WaitHandle ExecutionCompleteWaitHandle        {            get { return mAsyncWaitHandle; }        }    }}
StaThread
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace SynchronizationContextDemo{    internal class StaThread    {        private Thread mStaThread;        private IQueueReader
mQueueConsumer; private ManualResetEvent mStopEvent = new ManualResetEvent(false); internal StaThread(IQueueReader
reader) { mQueueConsumer = reader; mStaThread = new Thread(Run); mStaThread.Name = "STA Worker Thread"; mStaThread.SetApartmentState(ApartmentState.STA); } internal void Start() { mStaThread.Start(); } internal void Join() { mStaThread.Join(); } private void Run() { while (true) { bool stop = mStopEvent.WaitOne(0); if (stop) { break; } SendOrPostCallbackItem workItem = mQueueConsumer.Dequeue(); if (workItem != null) workItem.Execute(); } } internal void Stop() { mStopEvent.Set(); mQueueConsumer.ReleaseReader(); mStaThread.Join(); mQueueConsumer.Dispose(); } }}
StaSynchronizationContext
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;namespace SynchronizationContextDemo{    public class StaSynchronizationContext : SynchronizationContext, IDisposable    {        private BlockingQueue
mQueue; private StaThread mStaThread; public StaSynchronizationContext() : base() { mQueue = new BlockingQueue
(); mStaThread = new StaThread(mQueue); mStaThread.Start(); } public override void Send(SendOrPostCallback d, object state) { // create an item for execution SendOrPostCallbackItem item = new SendOrPostCallbackItem(d, state, ExecutionType.Send); // queue the item mQueue.Enqueue(item); // wait for the item execution to end item.ExecutionCompleteWaitHandle.WaitOne(); // if there was an exception, throw it on the caller thread, not the // sta thread. if (item.ExecutedWithException) throw item.Exception; } public override void Post(SendOrPostCallback d, object state) { // queue the item and don't wait for its execution. This is risky because // an unhandled exception will terminate the STA thread. Use with caution. SendOrPostCallbackItem item = new SendOrPostCallbackItem(d, state, ExecutionType.Post); mQueue.Enqueue(item); } public void Dispose() { mStaThread.Stop(); } public override SynchronizationContext CreateCopy() { return this; } }}
Main
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;using System.Diagnostics;namespace SynchronizationContextDemo{    public class Params    {        public string Output { get; set; }        public int CallCounter { get; set; }        public int OriginalThread { get; set; }    }    class Program    {        private static int mCount = 0;        private static StaSynchronizationContext mStaSyncContext = null;        static void Main(string[] args)        {            mStaSyncContext = new StaSynchronizationContext();            for (int i = 0; i < 100; i++)            {                ThreadPool.QueueUserWorkItem(NonStaThread);            }            Console.WriteLine("Processing");            Console.WriteLine("Press any key to dispose SyncContext");            Console.ReadLine();            mStaSyncContext.Dispose();        }        private static void NonStaThread(object state)        {            int id = Thread.CurrentThread.ManagedThreadId;            for (int i = 0; i < 10; i++)            {                var param = new Params { OriginalThread = id, CallCounter = i };                mStaSyncContext.Send(RunOnStaThread, param);                Debug.Assert(param.Output == "Processed", "Unexpected behavior by STA thread");            }        }        private static void RunOnStaThread(object state)        {            mCount++;            Console.WriteLine(mCount);            int id = Thread.CurrentThread.ManagedThreadId;            var args = (Params)state;            Trace.WriteLine("STA id " + id + " original thread " +                            args.OriginalThread + " call count " + args.CallCounter);            args.Output = "Processed";        }    }}

 

转载于:https://www.cnblogs.com/zhanjindong/archive/2013/03/24/2978446.html

你可能感兴趣的文章
DataSet之增删改查操作(DataGridView绑定)
查看>>
整理几个 RPC 框架
查看>>
移动Web触控事件总结
查看>>
LinkedBlockingDeque
查看>>
c 编译和链接过程
查看>>
大数据:“人工特征工程+线性模型”的尽头
查看>>
35.使用拦截器实现权限验证
查看>>
2016(第三届)智能家居世界大会
查看>>
php json的相关操作
查看>>
用实例讲解Spark Sreaming--转
查看>>
Online DDL与pt-online-schema-change
查看>>
sublimtext3 自定义编译环境
查看>>
UVALive 6893 The Big Painting hash
查看>>
Android Activity.startActivity流程简介
查看>>
AdapterView<T extends Adapter>
查看>>
zabbix监控-基本原理介绍
查看>>
mysql基于init-connect+binlog完成审计功能
查看>>
ORACLE中CHAR、VARCHAR、NVARCHAR
查看>>
BZOJ1864[ZJOI2006]三色二叉树[树形DP]
查看>>
Nginx+Tomcat+Memcached负载均衡集群服务搭建
查看>>