.Net的异步机制(线程间通信) - step 5

本文深入探讨了.Net中的线程间通信,介绍了如何在异步操作中实现线程通信,重点关注了SynchronizationContext对象及其在Windows Forms中的应用。通过接口ISynchronizeInvoke和类SynchronizationContext,讲解了同步和异步调用的不同实现,以及在不同线程间传递信息的方法。
摘要由CSDN通过智能技术生成

前几篇文章我已经对异步的操作进行的详细的解释.异步操作也是线程的一种,当我们开始一个异步操作(新线程),完成调用后需要和其他线程通信(可能需要告知状态信息),这时候我们就需要线程间的通信编程.

 

线程间通信

 

我们看下面的图


1

我们来看线程间通信的原理:线程(Thread B)和线程(Thread A)通信, 首先线程A 必须实现同步上下文对象(Synchronization Context), 线程B通过调用线程A的同步上下文对象来访问线程A,所有实现都是在同步上下文中完成的.线程B有两种方式来实现线程间的通信.

第一种:调用线程A的同步上下文对象,阻碍当前线程,执行红色箭头调用,直到黄色箭头返回(同步上下文执行完毕)才释放当前线程. (1->2->3->5)

第二种: 调用线程A的同步上下文对象(实际上是在开启一个新线程去执行,1->2->3->5) ,执行红色箭头,但并不阻碍当前线程(原有线程,1->4->5),绿色箭头继续执行.

文章中将会通过下面几个类来进行介绍:

1.         ISynchronizeInvoke 接口

2.         SynchronizationContext 类

3.         AsyncOperation / AsyncOperationManager 类

附:  同步上下文对象(Synchronization Context)是什么呢? 当我们访问上下文对象时候(多个对象可以存在于一个上下文中), 是使用代理的方式引用的,而不是直接引用的.这种方式可能是当多个对象访问上下文对象时候,先到达对象先访问,锁住,执行完毕再解锁,排队式访问.

 

1. ISynchronizeInvoke 接口

 

我们先来看下面一段异步的代码(Window Form控件下有1Button/1Label),但点击Button的时候,执行异步调用,完成后,告诉Window Form Label控件Text属性 Asynchronous End”.

Code1.1

 1          delegate   void  DoWork();
 2          private   void  button1_Click( object  sender, EventArgs e)
 3          {
 4            //辅助方法,查看当前线程
 5            Debug.WriteLine(string.Format("Window Form Method.Thread ID:#{0}",
Thread.CurrentThread.ManagedThreadId));
 6            //Label lblStatus 属于主线程的控件[1]
 7            this.lblStatus.Text = "Asynchronous Start.";
 8            //使用委托来调用异步方法
 9            DoWork work = DoWorkMethod;
10            work.BeginInvoke(OnWorkCallback, work);
11        }

12          void  OnWorkCallback(IAsyncResult asyncResult)
13          {
14            //辅助方法,查看当前线程
15            Debug.WriteLine(string.Format("Asynchronous Callback Method.Thread ID:#{0}",
Thread.CurrentThread.ManagedThreadId));
16            DoWork work = asyncResult.AsyncState as DoWork;
17            if (work != null)
18            {
19                work.EndInvoke(asyncResult);
20            }

21            // 报错:"线程间操作无效: 从不是创建控件“lblStatus”的线程访问它."
22            this.lblStatus.Text = "Asynchronous End"//上面注释[1]
23        }

24
25          void  DoWorkMethod()
26          {
27            Thread.Sleep(3000);//模拟耗时工作
28        }

运行代码,我们在第22行报错(异步方法体内).为什么呢?我们必须清楚的一点,windows应用窗体应用程序中,对窗体上控件属性的任何修改都必须在主线程中完成。不能从其他线程安全地访问控件的方法和属性。从Debug窗口中我们也可以看出(1.1).执行Button Click事件的时候,运行在线程ID =#10; 在异步的方法体内,运行在线程ID=#7.不同线程间不能直接通信.


1.1

为了解决这个问题,实现图1.1 #10 #7 的通信,下来开始认识ISynchronizeInvoke 接口(此接口来自.Net Framework 1.0),提供3个方法1个属性:

BeginInvoke / EndInvoke 方法 : 异步方法
Invoke
方法 : 同步方法
InvokeRequired
属性 : 判读来源的执行线程

 

下面我们看Code1.2的具体代码来说明(Code1.1改写,其中Label 改为ListBox)

Code1.2

 1          delegate   void  DoWork();
 2          private   void  button1_Click( object  sender, EventArgs e)
 3          {
 4            //更新状态,添加到Listbox 中
 5            AddValue("Asynchronous Start.");
 6            //使用委托来调用异步方法
 7            DoWork work = DoWorkMethod;
 8            work.BeginInvoke(OnWorkCallback, work);
 9        }

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值