异步编程 (一)

.NET常见的异步编程模式分为:编程

APM(Asynchronous Programming Model) 异步编程模型安全

EAP(Event-based Asynchronous Pattern) 事件异步模式多线程

TAP(Task-based Asynchronous Pattern)  任务异步模式异步

TPL(Task Parallel Pattern)      任务并行 模式异步编程

 

1.APM 异步编程模型

APM异步编程 经过begin 和end方法来操做,代指异步编程的开始和结束,下面经过几种异步模型来讲明APM的执行函数

Deletegate 的异步执行ui

static void Main()
        {
            Handler handler =Test;//代理指针
            Console.WriteLine("Invoke begin!");
            var tmp= handler.BeginInvoke("test", new AsyncCallback(ar =>//代理的执行
            {
                Console.WriteLine(ar.IsCompleted);
                handler.EndInvoke(ar);//结束代理
                Console.WriteLine("Invoke end!");
            }), null);

            Console.WriteLine("Main Thread");
            Console.Read();
        }

        public delegate void Handler(string name);//定义代理
        public static void Test(string name)
        {
                Console.WriteLine("the arg is:{0}", name);        
        }

执行结果:this

image

能够看到,代理的异步执行并无阻塞主线程,而是并行执行,代理的spa

BeginInvoke(string name,AsyncCallBack callback,object obj)线程

EndInvoke(IAsyncResult)

这是异步执行的两个方法,AsyncCallBack 是回调方法,name是传入方法的参数。IAsyncResult 定义以下:

public interface IAsyncResult
    {      
        bool IsCompleted { get; }       
        WaitHandle AsyncWaitHandle { get; }       
        object AsyncState { get; }
        bool CompletedSynchronously { get; }
    }

IsCompleted 异步线程是否结束,当用同步方式执行异步代理的时候能够用此属性来查询异步代理是否结束

AsyncWaitHandle 获取一个信号量,等待异步的执行完毕

AsyncState 传入的状态量

 

WindowForm的控件操做

在UI编程中,全部的UI操做,包括修改UI的属性如显示文本,颜色,样式等 都必须在UI线程上操做,可是编程过程当中,常常使用多线程编程,在咱们本身定义的线程中直接访问UI控件的属性或者修改UI控件的属性的时候,一般是不安全的

多线程访问窗口中的控件,能够在窗口的构造函数中将Form的CheckForIllegalCrossThreadCalls静态属性设置为false,可是不推荐这种操做。

 

安全访问的方式:把本身定义的线程中UI操做放到UI线程上操做,这样就不会再有不安全的操做;

Control类的 Invoke,BeginInvoke 内部实现以下:

a) Invoke (同步调用)先判断控件建立线程与当前线程是否相同,相同则直接调用委托方法;不然使用Win32API的PostMessage 异步执行,可是 Invoke 内部会调用IAsyncResult.AsyncWaitHandle等待执行完成。

b) BeginInvoke (异步调用)使用Win32API的PostMessage 异步执行,而且返回 IAsyncResult 对象。

2) InvokeRequired

获取一个值,该值指示调用线程是否与控件的建立线程相同。

public Form1()
        {
            InitializeComponent();
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<String>(ChangeText), "test");
            }
            else
            {
                ChangeText("test");
            }

        }
        private void ChangeText(String str)
        {
            this.Text += str;
        }

2.EAP 基于事件的异步编程
事件模型的异步编程,你们都是很熟悉的,特别是在UI编程中 VS作的很好,只须要 双击下控件,IDE就自动为控件注册事件,固然也能够定义本身的事件:

 1 public Form1()
 2         {
 3             InitializeComponent();
 4             this.NotifyEvent += () => {
 5                 Console.WriteLine("Event has been fired");
 6             };
 7 
 8         }
 9         public event NotifyHandler NotifyEvent;
10         public delegate void NotifyHandler();
11         public void OnNotify()
12         {
13             NotifyEvent?.Invoke();
14         }
15 
16         public void TestEvent()
17         {
18             OnNotify();
19         }
20 
21         private void button1_Click(object sender, EventArgs e)
22         {
23             TestEvent();
24         }
 
 

点击按钮以后,就能够触发事件了

相关文章
相关标签/搜索