SynchronizationContext

SendOrPostCallback xxx = vg => { Text ="内部: "+vg.ToString(); };

            dynamic vx = new { a = SynchronizationContext.Current, b = xxx };
            Thread td = new Thread(x =>
            {
                dynamic tmp = x;
                
                // SynchronizationContext ds = x as SynchronizationContext;
                for (int i = 0; i < 500; i++)
                {
                    System.Threading.Thread.Sleep(10);
                    //((SynchronizationContext)tmp.a).Post(v => { Text = v.ToString(); }, i + "   " + DateTime.Now);
                    ((SynchronizationContext)tmp.a).Post(tmp.b, i + "   " + DateTime.Now);

                }
              //  this.Invoke((MethodInvoker)delegate { MessageBox.Show("ok"); });

            });
            td.Start(vx);

  

  void uiexe(object cs)
        {
            Text = cs.ToString();
        }

  

//ThreadPool.QueueUserWorkItem(x =>
            //{
            //    for (int i = 0; i < 100; i++)
            //    {
            //        System.Threading.Thread.Sleep(10);
            //        ((SynchronizationContext)x).Post(y => { Text = i + "   " + DateTime.Now; }, null);
            //    }

            //}, SynchronizationContext.Current);

            SynchronizationContext nb = SynchronizationContext.Current;
            ThreadPool.QueueUserWorkItem(x =>
            {
                for (int i = 0; i < 100; i++)
                {
                    System.Threading.Thread.Sleep(10);
                    nb.Post(y => { Text = i + "   " + DateTime.Now; }, null);
                }

            }, null);

  

[STAThread]

static void Main()

{

    Application.EnableVisualStyles();

    Application.SetCompatibleTextRenderingDefault(false);



    // let's check the context here

    var context = SynchronizationContext.Current;

    if (context == null)

        MessageBox.Show("No context for this thread");

    else

        MessageBox.Show("We got a context");



    // create a form

    Form1 form = new Form1();



    // let's check it again after creating a form

    context = SynchronizationContext.Current;



    if (context == null)

        MessageBox.Show("No context for this thread");

    else

        MessageBox.Show("We got a context");



    if (context == null)

        MessageBox.Show("No context for this thread");



    Application.Run(new Form1());

}

  

而且它使用非常方便,只需要关注下面两个方法即可:

1.      Send:发送界面更新请求至主线程,阻塞当前线程直至返回。

2.      Post:发送界面更新请求至主线程,不阻塞当前线程。

实际上,他们都是同一个方法,只是 send 是同步,post 是异步

这是一个很简单的例子,也许看过的人都会说:根本就没有摆脱Control  和 From 啊!

诚然如此,为了摆脱Control,我们还需要封装一下,看下面的BackgroundWorker 类:

    class BackgroundWorker
    {
        public EventHandler<EventArgs> WorkerStarted;
        public EventHandler<ProgressEventArgs> ReportProgress;
        public EventHandler<EventArgs> WorkerCompleted;

        public SynchronizationContext Context { get; set; }

        public void Start()
        {
            Thread t = new Thread(() =>
            {
                Context.Post(SetStartState, null);

                for (int i = 0; i <= 10; i++)
                {
                    Thread.Sleep(new TimeSpan(0, 0, 1));
                    Context.Post(UpdateProgress, i * 10);
                }

                Thread.Sleep(new TimeSpan(0, 0, 1));
                Context.Post(SetCompletedState, null);
            }
            );
            t.Start();
        }

        private void SetStartState(object state)
        {
            if (WorkerStarted != null)
            {
                WorkerStarted(this, new EventArgs());
            }
        }

        private void SetCompletedState(object state)
        {
            if (WorkerCompleted != null)
            {
                WorkerCompleted(this, new EventArgs());
            }
        }

        private void UpdateProgress(object state)
        {
            if (ReportProgress != null)
            {
                ReportProgress(this, new ProgressEventArgs {Progress = Convert.ToInt32(state)});
            }
        }
    }

  

有两个特别的地方:

1. 构造的时候,需要提供SynchronizationContext 实例

2. 它的三个事件(WorkerStarted,ReportProgress, WorkerCompleted),都是在 post 方法里面触发的。这样做就可以确保事件的订阅方法脱离后台线程,进入主线程。

        protected override void OnLoad(EventArgs e)
        {
            _context = SynchronizationContext.Current;
        }

        private void btnWrapper_Click(object sender, EventArgs e)
        {
            btnWrapper.Enabled = false;

            BackgroundWorker worker = new BackgroundWorker {Context = SynchronizationContext.Current};
            worker.WorkerStarted += (o, args) => { txtWrapper.Text = "Running background thread..."; };
            worker.ReportProgress += (o, args) => { txtWrapper.Text = string.Format("Progress: {0}", args.Progress); };
            worker.WorkerCompleted += (o, args) =>
            {
                txtWrapper.Text = "Background thread completed";
                btnWrapper.Enabled = true;
            };

            worker.Start();
        }

  

    WebChannelFactory<JK.IXX> dd = new WebChannelFactory<JK.IXX>(new Uri("http://localhost/xxii"));
            //  ChannelFactory<JK.IXX> dd = new ChannelFactory<JK.IXX>(bd, "http://localhost/xxii");
            //   dd.Endpoint.Behaviors.Add(new WebHttpBehavior());
            //  WebOperationContext.Current.IncomingRequest.Headers.Add("dddd","ssss");
            dd.Endpoint.Behaviors.Add(new XEndpointBehavior());

            //SynchronizationContext.Current.Post(
            // SynchronizationContext

            JK.IXX service = dd.CreateChannel();
            IClientChannel clientchanel = service as IClientChannel;

            //IServiceChannel 
            using (OperationContextScope scope = new OperationContextScope(clientchanel))
            {
                var xddd = WebOperationContext.Current;


                xddd.OutgoingRequest.Headers.Add("ssss", "dddd" + DateTime.Now);

                //加不了
                //*****************************************************************************************
                //using (OperationContextScope scope = new OperationContextScope(iContextChannel))
                //{
                //MessageHeader<string> mh = new MessageHeader<string>("abcde");
                //MessageHeader header = mh.GetUntypedHeader("AuthKey", http://www.cjb.com/);
                //OperationContext.Current.OutgoingMessageHeaders.Add(header);

                //return func();
                //}

                //服务端: 

                //string authKey = string.Empty;
                //if (OperationContext.Current != null)
                //{
                //authKey = OperationContext.Current.IncomingMessageHeaders.GetHeader<string>("AuthKey", http://www.cjb.com);
                //}
                //*****************************************************************************************


                //调用方法获取消息头  
                string messHeader = service.getstr();
                MessageBox.Show(messHeader);
                Console.WriteLine(messHeader);
                Console.WriteLine("服务方法已调用");
            }

  

原文地址:https://www.cnblogs.com/xiangxiong/p/6802623.html