C#(2)

今天老師上課講到了異步編程。

一個異步過程調用發出後,調用者不能立刻得到結果。基於事件機制,實際處理這個調用的部件在完成後,通過狀態、通知和回調來通知調用者。比如,你現在要有一批數據要大數據要入庫,你又不想一邊入庫一邊等待返回結果,你可以用異步,將大數據推入一個隊列,然後另外一個線程來操作這個隊列裏面的數據入庫,入完了,就通知一下主線程。這段時間你的主線程可以做任何事。

首先提到了Asynchromous Programming Model,異步編寫模型是一種模式,該模式允許用更少的線程去做更多的操作,.NET
Framework很多類也實現了該模式,同時我們也可以自定義類來實現該模式,(也就是在自定義的類中實現返回類型爲IAsyncResult接口的BeginXXX方法和EndXXX
方法)委託類型也定義了BeginInvoke和EndInvoke方法。

以FileStream 爲例

同步方法

public override int Read(byte[] array,int offset, int count);

異步方法

public override IAsyncResult BeginRead(byte[] array, int offset, int numBytes, AsyncCallback userCallback, object stateObject);

結束異步的操作:

public override int EndRead(IAsyncResult asyncResult);

APM提供了四種方式供開發人員選擇:

1. 在調用BeginXxx方法的線程上調用EndXxx方法來得到異步操作的結果,但是這種方式會阻塞調用線程,知道操作完成之後調用線程才繼續運行

2. 查詢IAsyncResult的syncWaitHandle屬性,從而得到WaitHandle,然後再調用它的WaitOne方法來使一個線程阻塞並等待操作完成再調用EndXxx方法來獲得操作的結果。

3. 循環查詢IAsyncResult的IsComplete屬性,操作完成後再調用EndXxx方法來獲得操作返回的結果。

4. 使用 AsyncCallback委託來指定操作完成時要調用的方法,在操作完成後調用的方法中調用EndXxx操作來獲得異步操作的結果。

推薦使用第四種方法:

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections.Specialized;
using System.Collections;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class UseDelegateForAsyncCallback
    {
        static int requestCounter;
        static ArrayList hostData = new ArrayList();
        static StringCollection hostNames = new StringCollection();
        static void UpdateUserInterface()
        {
            // Print a message to indicate that the application
            // is still working on the remaining requests.
            Console.WriteLine("{0} requests remaining.", requestCounter);
        }
        public static void Main()
        {
            // Create the delegate that will process the results of the 
            // asynchronous request.
            AsyncCallback callBack = new AsyncCallback(ProcessDnsInformation);
            string host;
            do
            {
                Console.Write(" Enter the name of a host computer or <enter> to finish: ");
                host = Console.ReadLine();
                if (host.Length > 0)
                {
                    // Increment the request counter in a thread safe manner.
                    Interlocked.Increment(ref requestCounter);
                    // Start the asynchronous request for DNS information.
                    Dns.BeginGetHostEntry(host, callBack, host);
                 }
            } while (host.Length > 0);
            // The user has entered all of the host names for lookup.
            // Now wait until the threads complete.
            while (requestCounter > 0)
            {
                UpdateUserInterface();
            }
            // Display the results.
            for (int i = 0; i< hostNames.Count; i++)
            {
                object data = hostData [i];
                string message = data as string;
                // A SocketException was thrown.
                if (message != null)
                {
                    Console.WriteLine("Request for {0} returned message: {1}", 
                        hostNames[i], message);
                    continue;
                }
                // Get the results.
                IPHostEntry h = (IPHostEntry) data;
                string[] aliases = h.Aliases;
                IPAddress[] addresses = h.AddressList;
                if (aliases.Length > 0)
                {
                    Console.WriteLine("Aliases for {0}", hostNames[i]);
                    for (int j = 0; j < aliases.Length; j++)
                    {
                        Console.WriteLine("{0}", aliases[j]);
                    }
                }
                if (addresses.Length > 0)
                {
                    Console.WriteLine("Addresses for {0}", hostNames[i]);
                    for (int k = 0; k < addresses.Length; k++)
                    {
                        Console.WriteLine("{0}",addresses[k].ToString());
                    }
                }
            }
       }
        // The following method is called when each asynchronous operation completes.
        static void ProcessDnsInformation(IAsyncResult result)
        {
            string hostName = (string) result.AsyncState;
            hostNames.Add(hostName);
            try 
            {
                // Get the results.
                IPHostEntry host = Dns.EndGetHostEntry(result);
                hostData.Add(host);
            }
            // Store the exception message.
            catch (SocketException e)
            {
                hostData.Add(e.Message);
            }
            finally 
            {
                // Decrement the request counter in a thread-safe manner.
                Interlocked.Decrement(ref requestCounter);
            }
        }
    }
}
C# 5.0 async / await
異步對可能起阻止作用的活動(例如,應用程序訪問 Web 時)至關重要。 對Web 資源的訪問有時很慢或會延遲。 如果此類活動在同步過程中受阻,則整個應用程序必須等待。 在異步過程中,應用程序可繼續執行不依賴 Web 資源的其他工作,直至潛在阻止任務完成。

async Task<int> AccessTheWebAsync()
{
<span style="white-space:pre">	</span>HVpClient client = new HVpClient();
<span style="white-space:pre">	</span>Task<string> getStringTask = client.GetStringAsync("hVp://msdn.microsod.com");
<span style="white-space:pre">	</span>DoIndependentWork();
<span style="white-space:pre">	</span>string urlContents = await getStringTask;
<span style="white-space:pre">	</span>return urlContents.Length;
}


最後就是HttpClient

HttpClient是接收HttpResponseMessages和發送HttpRequestMessages的主要類,如果你習慣了使用WebClient或者是HttpWebRequest, 需要注意HttpClient和他們
不同的地方:

1、在HttpClient實例上配置擴展,設置默認的頭部,取消未完成的請求和更多的設置。
2、你通過一個單一的HttpClient實例,它有自己的連接池。
3、HttpClients不與特定的HTTP服務器綁定,你可以使用相同的HttpClient實例提交任何HTTP請求。
4、你可以用HttpClient爲特定的站點創建特殊的Client
5、HttpClient採用新的型模式處理異步請求使它更容易管理和協調更多的請求。

HttpClient - Get

<pre name="code" class="csharp">client.GetAsync(_address).ConenueWith((requestTask)=>
{
	//Get HTTP response from completed task.
	HttpResponseMessage response = requestTask.Result;
	//Check that response was successful or throw exception
	response.EnsureSuccessStatusCode();
	//Read response asynchronously as JsonValue and write out top facts for each country
	response.Content.ReadAsAsync<JsonArray>().ConenueWith((readTask)=>{
		Console.WriteLine("First 50 countries listed by The World Bank...");
		foreach(var country in readTask.Result[1])
		{
		Console.WriteLine("{0},Country Code:{1},Capital:{2},Laetude:{3},Longitude:{4}",country.Value["name"],
		country.Value["iso2Code"],country.Value["capitalCity"],country.Value["laetude"],country.Value["longitude"]);
		}
	});
});

HttpClient-Post

Uri serviceReq = new Uri(serviceAddress);
HttpClient client = new HttpClient();
HttpContent content = new StringContent(@"{ ""value"": ""test""}");
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
// Send a request asynchronously continue when complete
client.PostAsync(serviceReq, content).ContinueWith(
(requestTask) =>
{
// Get HTTP response from completed task.
HttpResponseMessage response = requestTask.Result;
// Check that response was successful or throw exception
response.EnsureSuccessStatusCode();
// Read response asynchronously as JsonValue and write out top facts for each country
response.Content.ReadAsAsync<string>().ContinueWith(
(readTask) =>
{
Console.WriteLine(readTask.Result);
});
});
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章