程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 多線程操作之異步委托

多線程操作之異步委托

編輯:C#入門知識

在應屆生找工作的時候,多線程操作幾乎是所有的公司都會問及的一個基本問題。

這裡做了一個多線程操作的總結,這裡總結了通過異步委托來實現多線程操作。

定義一個委托,是創建一個線程的最簡單的方法,並且異步調用它。委托是方法的類型安全的引用。同時委托還智齒異步調用方法。

委托使用線程池來完成異步任務。

當自己的程序使用異步委托的時候,委托會自動創建ige執行線程的任務。委托使用線程池完成異步任務,所有的異步委托調用,都會通過調用系統線程池中的線程來完成調用異步任務。

在下面的簡單例子中,我們定義了一個異步委托,並在每次輸出的時候顯示該函數運行在哪個線程中。

在異步委托中,可以使用三種技術來異步的調用委托。下面分別介紹三種調用異步委托的方法。

1. 投票判斷異步委托是否完成

在委托中調用BeginInvoke()方法,返回IAsyncResult結果。程序的源代碼如下:

[csharp] 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 
 
namespace AsyncDelegate 

    class Program 
    { 
        public delegate int TakeSomeTimeDelegate(int data,int ms); 
 
        static void Main(string[] args) 
        { 
            TakeSomeTimeDelegate dl=TakeSomeTime; 
            IAsyncResult ar=dl.BeginInvoke(1,200,null,null); 
 
            while (!ar.IsCompleted) 
            { 
                Console.WriteLine("."); 
                Console.WriteLine("Run in thread:" + Thread.CurrentThread.ManagedThreadId); 
                Thread.Sleep(50); 
            } 
 
            int result = dl.EndInvoke(ar); 
            Console.WriteLine("Result:{0}", result); 
        } 
 
        static int TakeSomeTime(int data, int ms) 
        { 
            Console.WriteLine("TakeSomeTime started!"); 
            Console.WriteLine("Run in thread:"+Thread.CurrentThread.ManagedThreadId); 
            Thread.Sleep(ms); 
            Console.WriteLine("TakeSomeTime Completed!"); 
            return ++data; 
        } 
    } 

該程序的輸出結果如圖:

 

可以看到主線程和異步委托線程是同時執行的。

如果在委托結束之前不等待委托完成其他任務就結束主線程,委托線程就會停止。

int result = dl.EndInvoke(ar); 這裡的EndInvoke()函數會一直等在異步委托完成並在異步委托完成之前阻斷主線程。這樣就可以通過這個函數保證異步委托能夠正確完成。

 

2. 等待句柄判斷異步委托完成

通過AsyncWatiHandle屬性,訪問等待句柄。WaitOne()方法阻斷當前線程,直到異步調用線程完成返回可以利用的句柄以後再執行當前線程。

程序:

[html]
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 
 
namespace AsyncDelegate 

    class Program 
    { 
        public delegate int TakeSomeTimeDelegate(int data,int ms); 
 
        static void Main(string[] args) 
        { 
            TakeSomeTimeDelegate dl=TakeSomeTime; 
            IAsyncResult ar=dl.BeginInvoke(1,200,null,null); 
 
            while (true) 
            { 
                Console.WriteLine("."); 
                Console.WriteLine("Run in thread:" + Thread.CurrentThread.ManagedThreadId); 
                if (ar.AsyncWaitHandle.WaitOne(100, false)) 
                { 
                    Console.WriteLine("Can get the result now"); 
                    break; 
                } 
            } 
 
            //while (!ar.IsCompleted) 
            //{ 
            //    Console.WriteLine("."); 
            //    Console.WriteLine("Run in thread:" + Thread.CurrentThread.ManagedThreadId); 
            //    Thread.Sleep(50); 
            //} 
 
            int result = dl.EndInvoke(ar); 
            Console.WriteLine("Result:{0}", result); 
        } 
 
        static int TakeSomeTime(int data, int ms) 
        { 
            Console.WriteLine("TakeSomeTime started!"); 
            Console.WriteLine("Run in thread:"+Thread.CurrentThread.ManagedThreadId); 
            Thread.Sleep(ms); 
            Console.WriteLine("TakeSomeTime Completed!"); 
            return ++data; 
        } 
    } 

運行結果:

 

 

 

ar.AsyncWaitHandle.WaitOne()阻斷了當前線程, 直到異步調用線程完成獲得可以利用的句柄以後再次執行當前線程。

 

3. 利用異步回調函數判斷異步調用線程是否結束

 

回調函數的操作比較復雜, 而且對於程序的理解和維護造成非常大的困難。所以一般情況下能不用回調函數就不要使用回調函數。

 

使用回調函數,必須注意這個函數從委托線程中調用,而不是從主線程中調用回調函數。

[csharp]
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 
 
namespace AsyncDelegate 

    class Program 
    { 
        public delegate int TakeSomeTimeDelegate(int data,int ms); 
 
        static void Main(string[] args) 
        { 
            TakeSomeTimeDelegate dl=TakeSomeTime; 
            IAsyncResult ar = dl.BeginInvoke(1, 200, TakeSomeTimeCompleted, dl); 
            for (int i = 0; i < 10;i++ ) 
            { 
                Console.WriteLine("."); 
                Console.WriteLine("Run in thread:" + Thread.CurrentThread.ManagedThreadId); 
                Thread.Sleep(50); 
            } 
 
            //int result = dl.EndInvoke(ar); 
            //Console.WriteLine("Result:{0}", result); 
        } 
 
        static int TakeSomeTime(int data, int ms) 
        { 
            Console.WriteLine("TakeSomeTime started!"); 
            Console.WriteLine("Run in thread:"+Thread.CurrentThread.ManagedThreadId); 
            Thread.Sleep(ms); 
            Console.WriteLine("TakeSomeTime Completed!"); 
            return ++data; 
        } 
 
        static void TakeSomeTimeCompleted(IAsyncResult ar) 
        { 
            if (ar==null) 
            { 
                throw new ArgumentNullException("ar"); 
            } 
            TakeSomeTimeDelegate dl = ar.AsyncState as TakeSomeTimeDelegate; 
            int result = dl.EndInvoke(ar); 
            Console.WriteLine("result : {0}", result); 
            //Console.WriteLine("Run in thread:" + Thread.CurrentThread.ManagedThreadId); 
        } 
    } 

 

運行結果:

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved