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

WinForm 進度條

編輯:C#入門知識

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace LongTime
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // 進度發生變化之後的回調方法
        private void workder_ValueChanged(object sender, Business.ValueEventArgs e)
        {
            System.Windows.Forms.MethodInvoker invoker = () =>
                {
                    this.progressBar1.Value = e.Value;
                };

            if (this.progressBar1.InvokeRequired)
            {
                this.progressBar1.Invoke(invoker);
            }
            else
            {
                invoker();
            }
        }


        private void button1_Click(object sender, EventArgs e)
        {
            // 禁用按鈕
            this.button1.Enabled = false;

            // 實例化業務對象
            LongTime.Business.LongTimeWork workder = new Business.LongTimeWork();

            workder.ValueChanged += new Business.ValueChangedEventHandler(workder_ValueChanged);

            // 使用異步方式調用長時間的方法
            Action handler = new Action(workder.LongTimeMethod);
            handler.BeginInvoke(
                new AsyncCallback(this.AsyncCallback),
                handler
                );
        }

        // 結束異步操作
        private void AsyncCallback(IAsyncResult ar)
        {
            // 標准的處理步驟
            Action handler = ar.AsyncState as Action;
            handler.EndInvoke(ar);

            MessageBox.Show("工作完成!");

            System.Windows.Forms.MethodInvoker invoker = () =>
            {
                // 重新啟用按鈕
                this.button1.Enabled = true;
            };

            if (this.InvokeRequired)
            {
                this.Invoke(invoker);
            }
            else
            {
                invoker();
            }
        }

    }
}

  

工作類:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LongTime.Business
{
    // 定義事件的參數類
    public class ValueEventArgs 
        : EventArgs
    {
        public int Value { set; get;}
    }

    // 定義事件使用的委托
    public delegate void ValueChangedEventHandler( object sender, ValueEventArgs e);

    class LongTimeWork
    {
        // 定義一個事件來提示界面工作的進度
        public event ValueChangedEventHandler ValueChanged;

        // 觸發事件的方法
        protected void OnValueChanged( ValueEventArgs e)
        {
            if( this.ValueChanged != null)
            {
                this.ValueChanged( this, e);
            }
        }

        public void LongTimeMethod()
        {
            for (int i = 0; i < 15; i++)
            {
                // 進行工作
                System.Threading.Thread.Sleep(1000);

                // 觸發事件
                ValueEventArgs e = new ValueEventArgs() { Value = i+1};
                this.OnValueChanged(e);
            }
        }
    }
}

  

 *********************************************

一、C#線程概述

在操作系統中一個進程至少要包含一個線程,然後,在某些時候需要在同一個進程中同時執行多項任務,或是為了提供程序的性能,將要執行的任務分解成多個子任務執行。這就需要在同一個進程中開啟多個線程。我們使用C#編寫一個應用程序(控制台或桌面程序都可以),然後運行這個程序,並打開windows任務管理器,這時我們就會看到這個應用程序中所含有的線程數,如下圖所示。

應用程序中所含有的線程數

如果任務管理器沒有“線程數”列,可以【查看】>【選擇列】來顯示“線程計數”列。從上圖可以看出,幾乎所有的進程都擁有兩個以上的線程。從而可以看出,線程是提供應用程序性能的重要手段之一,尤其在多核CPU的機器上尤為明顯。

二、用委托(Delegate)的BeginInvoke和EndInvoke方法操作線程

在C#中使用線程的方法很多,使用委托的BeginInvoke和EndInvoke方法就是其中之一。BeginInvoke方法可以使用線程異步地執行委托所指向的方法。然後通過EndInvoke方法獲得方法的返回值(EndInvoke方法的返回值就是被調用方法的返回值),或是確定方法已經被成功調用。我們可以通過四種方法從EndInvoke方法來獲得返回值。

三、直接使用EndInvoke方法來獲得返回值

當使用BeginInvoke異步調用方法時,如果方法未執行完,EndInvoke方法就會一直阻塞,直到被調用的方法執行完畢。如下面的代碼所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace MyThread
{
class Program
{
private static int newTask(int ms)
{
Console.WriteLine("任務開始");
Thread.Sleep(ms);
Random random = new Random();
int n = random.Next(10000);
Console.WriteLine("任務完成");
return n;
}

private delegate int NewTaskDelegate(int ms);


static void Main(string[] args)
{
NewTaskDelegate task = newTask;
IAsyncResult asyncResult = task.BeginInvoke(2000, null, null);

// EndInvoke方法將被阻塞2秒
int result = task.EndInvoke(asyncResult);
Console.WriteLine(result);
}
}
}

在運行上面的程序後,由於newTask方法通過Sleep延遲了2秒,因此,程序直到2秒後才輸出最終結果(一個隨機整數)。如果不調用EndInvoke方法,程序會立即退出,這是由於使用BeginInvoke創建的線程都是後台線程,這種線程一但所有的前台線程都退出後(其中主線程就是一個前台線程),不管後台線程是否執行完畢,都會結束線程,並退出程序。關於前台和後台線程的詳細內容,將在後面的部分講解。

讀者可以使用上面的程序做以下實驗。首先在Main方法的開始部分加入如下代碼:

Thread.Sleep(10000);
以使Main方法延遲10秒鐘再執行下面的代碼,然後按Ctrl+F5運行程序,並打開企業管理器,觀察當前程序的線程數,假設線程數是4,在10秒後,線程數會增至5,這是因為調用BeginInvoke方法時會建立一個線程來異步執行newTask方法,因此,線程會增加一個。

四、使用IAsyncResult asyncResult屬性來判斷異步調用是否完成

雖然上面的方法可以很好地實現異步調用,但是當調用EndInvoke方法獲得調用結果時,整個程序就象死了一樣,這樣做用戶的感覺並不會太好,因此,我們可以使用asyncResult來判斷異步調用是否完成,並顯示一些提示信息。這樣做可以增加用戶體驗。代碼如下:

static void Main(string[] args)
{
NewTaskDelegate task = newTask;
IAsyncResult asyncResult = task.BeginInvoke(2000, null, null);

while (!asyncResult.IsCompleted)
{
Console.Write("*");
Thread.Sleep(100);
}
// 由於異步調用已經完成,因此, EndInvoke會立刻返回結果
int result = task.EndInvoke(asyncResult);
Console.WriteLine(result);
}

上面代碼的執行結果如下圖所示。

執行結果

由於是異步,所以“*”可能會在“任務開始”前輸出,如上圖所示。

五、使用WaitOne方法等待異步方法執行完成

使用WaitOne方法是另外一種判斷異步調用是否完成的方法。代碼如下:

static void Main(string[] args)
{
NewTaskDelegate task = newTask;
IAsyncResult asyncResult = task.BeginInvoke(2000, null, null);

while (!asyncResult.AsyncWaitHandle.WaitOne(100, false))
{
Console.Write("*");
}

int result = task.EndInvoke(asyncResult);
Console.WriteLine(result);
}

WaitOne的第一個參數表示要等待的毫秒數,在指定時間之內,WaitOne方法將一直等待,直到異步調用完成,並發出通知,WaitOne方法才返回true。當等待指定時間之後,異步調用仍未完成,WaitOne方法返回false,如果指定時間為0,表示不等待,如果為-1,表示永遠等待,直到異步調用完成。

六、使用回調方式返回結果

上面介紹的幾種方法實際上只相當於一種方法。這些方法雖然可以成功返回結果,也可以給用戶一些提示,但在這個過程中,整個程序就象死了一樣(如果讀者在GUI程序中使用這些方法就會非常明顯),要想在調用的過程中,程序仍然可以正常做其它的工作,就必須使用異步調用的方式。下面我們使用GUI程序來編寫一個例子,代碼如下:

private delegate int MyMethod();
private int method()
{
Thread.Sleep(10000);
return 100;
}
private void MethodCompleted(IAsyncResult asyncResult)
{
if (asyncResult == null) return;
textBox1.Text = (asyncResult.AsyncState as
MyMethod).EndInvoke(asyncResult).ToString();
}

private void button1_Click(object sender, EventArgs e)
{

MyMethod my = method;
IAsyncResult asyncResult = my.BeginInvoke(MethodCompleted, my);
}

要注意的是,這裡使用了BeginInvoke方法的最後兩個參數(如果被調用的方法含有參數的話,這些參數將作為BeginInvoke的前面一部分參數,如果沒有參數,BeginInvoke就只有兩個參數了)。第一個參數是回調方法委托類型,這個委托只有一個參數,就是IAsyncResult,如MethodCompleted方法所示。當method方法執行完後,系統會自動調用MethodCompleted方法。BeginInvoke的第二個參數需要向MethodCompleted方法中傳遞一些值,一般可以傳遞被調用方法的委托,如上面代碼中的my。這個值可以使用IAsyncResult.AsyncState屬性獲得。

由於上面的代碼通過異步的方式訪問的form上的一個textbox,因此,需要按ctrl+f5運行程序(不能直接按F5運行程序,否則無法在其他線程中訪問這個textbox,關於如果在其他線程中訪問GUI組件,並在後面的部分詳細介紹)。並在form上放一些其他的可視控件,然在點擊button1後,其它的控件仍然可以使用,就象什麼事都沒有發生過一樣,在10秒後,在textbox1中將輸出100。

七、其他組件的BeginXXX和EndXXX方法

在其他的.net組件中也有類似BeginInvoke和EndInvoke的方法,如System.Net.HttpWebRequest類的BeginGetResponse和EndGetResponse方法,下面是使用這兩個方法的一個例子:

private void requestCompleted(IAsyncResult asyncResult)
{
if (asyncResult == null) return;
System.Net.HttpWebRequest hwr = asyncResult.AsyncState as System.Net.HttpWebRequest;
System.Net.HttpWebResponse response =
(System.Net.HttpWebResponse)hwr.EndGetResponse(asyncResult);
System.IO.StreamReader sr = new
System.IO.StreamReader(response.GetResponseStream());
textBox1.Text = sr.ReadToEnd();
}
private delegate System.Net.HttpWebResponse RequestDelegate(System.Net.HttpWebRequest request);

private void button1_Click(object sender, EventArgs e)
{
System.Net.HttpWebRequest request =
(System.Net.HttpWebRequest)System.Net.WebRequest.Create("http://www.cnblogs.com");
IAsyncResult asyncResult =request.BeginGetResponse(requestCompleted, request);
}

以上介紹的就是C#線程中BeginInvoke和EndInvoke方法。

 

 *****************************************************

 

C# Winform異步調用詳解 (2010-12-29 10:47:30)轉載▼
標簽: asynccallback iasyncresult asyncstate 異步調用 waithandle delegat 分類: C#/ASP.Net/VB.Net
C#異步調用四大方法是什麼呢?C#異步調用四大方法的使用是如何進行的呢?讓我們首先了解下什麼時候用到C#異步調用:
.NET Framework 允許您C#異步調用任何方法。定義與您需要調用的方法具有相同簽名的委托;公共語言運行庫將自動為該委托定義具有適當簽名的 BeginInvoke 和 EndInvoke 方法。
BeginInvoke 方法用於啟動C#異步調用。它與您需要異步執行的方法具有相同的參數,只不過還有兩個額外的參數(將在稍後描述)。BeginInvoke 立即返回,不等待C#異步調用完成。BeginInvoke 返回 IasyncResult,可用於監視調用進度。
EndInvoke 方法用於檢索C#異步調用結果。調用 BeginInvoke 後可隨時調用 EndInvoke 方法;如果C#異步調用未完成,EndInvoke 將一直阻塞到C#異步調用完成。EndInvoke 的參數包括您需要異步執行的方法的 out 和 ref 參數(在 Visual Basic 中為 ByRef 和 ByRef)以及由 BeginInvoke 返回的 IAsyncResult。
注意:Visual Studio .NET 中的智能感知功能會顯示 BeginInvoke 和 EndInvoke 的參數。如果您沒有使用 Visual Studio 或類似的工具,或者您使用的是 C# 和 Visual Studio .NET,請參見異步方法簽名獲取有關運行庫為這些方法定義的參數的描述。
一.C#異步調用四大方法詳解
本主題中的代碼演示了四種使用 BeginInvoke 和 EndInvoke 進行C#異步調用的常用方法。調用了 BeginInvoke 後,可以:
· 進行某些操作,然後調用 EndInvoke 一直阻塞到調用完成。
· 使用 IAsyncResult.AsyncWaitHandle 獲取 WaitHandle,使用它的 WaitOne 方法將執行一直阻塞到發出 WaitHandle 信號,然後調用 EndInvoke。
· 輪詢由 BeginInvoke 返回的 IAsyncResult,確定C#異步調用何時完成,然後調用 EndInvoke。
· 將用於回調方法的委托傳遞給 BeginInvoke。該方法在C#異步調用完成後在 ThreadPool 線程上執行,它可以調用 EndInvoke。
警告:始終在C#異步調用完成後調用 EndInvoke。
測試方法和異步委托
四個示例全部使用同一個長期運行的測試方法 TestMethod。該方法顯示一個表明它已開始處理的控制台信息,休眠幾秒鐘,然後結束。TestMethod 有一個 out 參數(在 Visual Basic 中為 ByRef),它演示了如何將這些參數添加到 BeginInvoke 和 EndInvoke 的簽名中。您可以用類似的方式處理 ref 參數(在 Visual Basic 中為 ByRef)。
下面的代碼示例顯示 TestMethod 以及代表 TestMethod 的委托;若要使用任一示例,請將示例代碼追加到這段代碼中。
注意 為了簡化這些示例,TestMethod 在獨立於 Main() 的類中聲明。或者,TestMethod 可以是包含 Main() 的同一類中的 static 方法(在 Visual Basic 中為 Shared)。
using System;
using System.Threading;

public class AsyncDemo {
// The method to be executed asynchronously.
//
public string TestMethod(
int callDuration, out int threadId) {
Console.WriteLine("Test method begins.");
Thread.Sleep(callDuration);
threadId = AppDomain.GetCurrentThreadId();
return "MyCallTime was " + callDuration.ToString();
}
}

// The delegate must have the same signature as the method
// you want to call asynchronously.
public delegate string AsyncDelegate(
int callDuration, out int threadId);


using System;
using System.Threading;

public class AsyncDemo {
// The method to be executed asynchronously.
//
public string TestMethod(
int callDuration, out int threadId) {
Console.WriteLine("Test method begins.");
Thread.Sleep(callDuration);
threadId = AppDomain.GetCurrentThreadId();
return "MyCallTime was " + callDuration.ToString();
}
}

// The delegate must have the same signature as the method
// you want to call asynchronously.
public delegate string AsyncDelegate(
int callDuration, out int threadId);
0x01:C#異步調用四大方法之使用 EndInvoke 等待異步調用
異步執行方法的最簡單方式是以 BeginInvoke 開始,對主線程執行一些操作,然後調用 EndInvoke。EndInvoke 直到C#異步調用完成後才返回。這種技術非常適合文件或網絡操作,但是由於它阻塞 EndInvoke,所以不要從用戶界面的服務線程中使用它。
public class AsyncMain {
static void Main(string[] args) {
// The asynchronous method puts the thread id here.
int threadId;

// Create an instance of the test class.
AsyncDemo ad = new AsyncDemo();

// Create the delegate.
AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);

// Initiate the asychronous call.
IAsyncResult ar = dlgt.BeginInvoke(3000,
out threadId, null, null);

Thread.Sleep(0);
Console.WriteLine("Main thread {0} does some work.",
AppDomain.GetCurrentThreadId());

// Call EndInvoke to Wait for
//the asynchronous call to complete,
// and to retrieve the results.
string ret = dlgt.EndInvoke(out threadId, ar);

Console.WriteLine("The call executed on thread {0},
with return value \"{1}\".", threadId, ret);
}
}
0x02:C#異步調用四大方法之使用 WaitHandle 等待異步調用
等待 WaitHandle 是一項常用的線程同步技術。您可以使用由 BeginInvoke 返回的 IAsyncResult 的 AsyncWaitHandle 屬性來獲取 WaitHandle。C#異步調用完成時會發出 WaitHandle 信號,而您可以通過調用它的 WaitOne 等待它。
如果您使用 WaitHandle,則在C#異步調用完成之後,但在通過調用 EndInvoke 檢索結果之前,可以執行其他處理。
public class AsyncMain {
static void Main(string[] args) {
// The asynchronous method puts the thread id here.
int threadId;

// Create an instance of the test class.
AsyncDemo ad = new AsyncDemo();

// Create the delegate.
AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);

// Initiate the asychronous call.
IAsyncResult ar = dlgt.BeginInvoke(3000,
out threadId, null, null);

Thread.Sleep(0);
Console.WriteLine("Main thread {0} does some work.",
AppDomain.GetCurrentThreadId());

// Wait for the WaitHandle to become signaled.
ar.AsyncWaitHandle.WaitOne();

// Perform additional processing here.
// Call EndInvoke to retrieve the results.
string ret = dlgt.EndInvoke(out threadId, ar);

Console.WriteLine("The call executed on thread {0},
with return value \"{1}\".", threadId, ret);
}
}
0x03:C#異步調用四大方法之輪詢異步調用完成
您可以使用由 BeginInvoke 返回的 IAsyncResult 的 IsCompleted 屬性來發現C#異步調用何時完成。從用戶界面的服務線程中進行C#異步調用時可以執行此操作。輪詢完成允許用戶界面線程繼續處理用戶輸入。
public class AsyncMain {
static void Main(string[] args) {
// The asynchronous method puts the thread id here.
int threadId;

// Create an instance of the test class.
AsyncDemo ad = new AsyncDemo();

// Create the delegate.
AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);

// Initiate the asychronous call.
IAsyncResult ar = dlgt.BeginInvoke(3000,
out threadId, null, null);

// Poll while simulating work.
while(ar.IsCompleted == false) {
Thread.Sleep(10);
}

// Call EndInvoke to retrieve the results.
string ret = dlgt.EndInvoke(out threadId, ar);

Console.WriteLine("The call executed on thread {0},
with return value \"{1}\".", threadId, ret);
}
}
0x04:C#異步調用四大方法之異步調用完成時執行回調方法
如果啟動異步調用的線程不需要處理調用結果,則可以在調用完成時執行回調方法。回調方法在 ThreadPool 線程上執行。
要使用回調方法,必須將代表該方法的 AsyncCallback 委托傳遞給 BeginInvoke。也可以傳遞包含回調方法將要使用的信息的對象。例如,可以傳遞啟動調用時曾使用的委托,以便回調方法能夠調用 EndInvoke。
public class AsyncMain {
// Asynchronous method puts the thread id here.
private static int threadId;

static void Main(string[] args) {
// Create an instance of the test class.
AsyncDemo ad = new AsyncDemo();

// Create the delegate.
AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);

// Initiate the asychronous call. Include an AsyncCallback
// delegate reDIVsenting the callback method, and the data
// needed to call EndInvoke.
IAsyncResult ar = dlgt.BeginInvoke(3000,
out threadId,
new AsyncCallback(CallbackMethod),
dlgt );

Console.WriteLine("DIVss Enter to close application.");
Console.ReadLine();
}

// Callback method must have the same signature as the
// AsyncCallback delegate.
static void CallbackMethod(IAsyncResult ar) {
// Retrieve the delegate.
AsyncDelegate dlgt = (AsyncDelegate) ar.AsyncState;

// Call EndInvoke to retrieve the results.
string ret = dlgt.EndInvoke(out threadId, ar);

Console.WriteLine("The call executed on thread {0},
with return value \"{1}\".", threadId, ret);
}
}

二.C#異步調用四大方法的基本內容就向你介紹到這裡,下面看有回調函數的WebRequest和WebResponse的異步操作。

using System;
using System.Net;
using System.Threading;
using System.Text;
using System.IO;


// RequestState 類用於通過
// 異步調用傳遞數據
public class RequestState
{
const int BUFFER_SIZE = 1024;
public StringBuilder RequestData;
public byte[] BufferRead;
public HttpWebRequest Request;
public Stream ResponseStream;
// 創建適當編碼類型的解碼器
public Decoder StreamDecode = Encoding.UTF8.GetDecoder();

public RequestState()
{
BufferRead = new byte[BUFFER_SIZE];
RequestData = new StringBuilder("");
Request = null;
ResponseStream = null;
}
}

// ClientGetAsync 發出異步請求
class ClientGetAsync
{
public static ManualResetEvent allDone = new ManualResetEvent(false);
const int BUFFER_SIZE = 1024;

public static void Main(string[] args)
{

if (args.Length < 1)
{
showusage();
return;
}

// 從命令行獲取 URI
Uri HttpSite = new Uri(args[0]);

// 創建請求對象
HttpWebRequest wreq = (HttpWebRequest)WebRequest.Create(HttpSite);

// 創建狀態對象
RequestState rs = new RequestState();

// 將請求添加到狀態,以便它可以被來回傳遞
rs.Request = wreq;

// 發出異步請求
IAsyncResult r = (IAsyncResult)wreq.BeginGetResponse(new AsyncCallback(RespCallback), rs);

// 將 ManualResetEvent 設置為 Wait,
// 以便在調用回調前,應用程序不退出
allDone.WaitOne();
}

public static void showusage()
{
Console.WriteLine("嘗試獲取 (GET) 一個 URL");
Console.WriteLine("\r\n用法::");
Console.WriteLine("ClientGetAsync URL");
Console.WriteLine("示例::");
Console.WriteLine("ClientGetAsync http://www.microsoft.com/net/");
}

private static void RespCallback(IAsyncResult ar)
{
// 從異步結果獲取 RequestState 對象
RequestState rs = (RequestState)ar.AsyncState;

// 從 RequestState 獲取 HttpWebRequest
HttpWebRequest req = rs.Request;

// 調用 EndGetResponse 生成 HttpWebResponse 對象
// 該對象來自上面發出的請求
HttpWebResponse resp = (HttpWebResponse)req.EndGetResponse(ar);

// 既然我們擁有了響應,就該從
// 響應流開始讀取數據了
Stream ResponseStream = resp.GetResponseStream();

// 該讀取操作也使用異步完成,所以我們
// 將要以 RequestState 存儲流
rs.ResponseStream = ResponseStream;

// 請注意,rs.BufferRead 被傳入到 BeginRead。
// 這是數據將被讀入的位置。
IAsyncResult iarRead = ResponseStream.BeginRead(rs.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), rs);
}


private static void ReadCallBack(IAsyncResult asyncResult)
{
// 從 asyncresult 獲取 RequestState 對象
RequestState rs = (RequestState)asyncResult.AsyncState;

// 取出在 RespCallback 中設置的 ResponseStream
Stream responseStream = rs.ResponseStream;

// 此時 rs.BufferRead 中應該有一些數據。
// 讀取操作將告訴我們那裡是否有數據
int read = responseStream.EndRead(asyncResult);

if (read > 0)
{
// 准備 Char 數組緩沖區,用於向 Unicode 轉換
Char[] charBuffer = new Char[BUFFER_SIZE];

// 將字節流轉換為 Char 數組,然後轉換為字符串
// len 顯示多少字符被轉換為 Unicode
int len = rs.StreamDecode.GetChars(rs.BufferRead, 0, read, charBuffer, 0);
String str = new String(charBuffer, 0, len);

// 將最近讀取的數據追加到 RequestData stringbuilder 對象中,
// 該對象包含在 RequestState 中
rs.RequestData.Append(str);


// 現在發出另一個異步調用,讀取更多的數據
// 請注意,將不斷調用此過程,直到
// responseStream.EndRead 返回 -1
IAsyncResult ar = responseStream.BeginRead(rs.BufferRead, 0, BUFFER_SIZE, new AsyncCallback(ReadCallBack), rs);
}
else
{
if (rs.RequestData.Length > 1)
{
// 所有數據都已被讀取,因此將其顯示到控制台
string strContent;
strContent = rs.RequestData.ToString();
Console.WriteLine(strContent);
}

// 關閉響應流
responseStream.Close();

// 設置 ManualResetEvent,以便主線程可以退出
allDone.Set();
}
return;
}
}
在這裡有回調函數,且異步回調中又有異步操作。
首先是異步獲得ResponseStream,然後異步讀取數據。
這個程序非常經典。從中可以學到很多東西的。我們來共同探討。
總結
上面說過,.net framework 可以異步調用任何方法。所以異步用處廣泛。
在.net framework 類庫中也有很多異步調用的方法。一般都是已Begin開頭End結尾構成一對,異步委托方法,外加兩個回調函數和AsyncState參數,組成異步操作的宏觀體現。所以要做異步編程,不要忘了委托delegate、Begin,End,AsyncCallBack委托,AsyncState實例(在回調函數中通過IAsyncResult.AsyncState來強制轉換),IAsycResult(監控異步),就足以理解異步真谛了

資源來自網絡,分別為:
http://www.cnblogs.com/ericwen/archive/2008/03/12/1101801.html
http://developer.51cto.com/art/200908/145541.htm

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