異步編程 (一)

.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         }
 
 

點擊按鈕以後,就能夠觸發事件了

相關文章
相關標籤/搜索