日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > C# >内容正文

C#

[转] C#异步操作

發(fā)布時(shí)間:2023/12/10 C# 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [转] C#异步操作 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Title

通過(guò)委托實(shí)現(xiàn)異步調(diào)用中BeginInvoke及回調(diào)函數(shù)的使用

通過(guò)委托實(shí)現(xiàn)異步調(diào)用的步驟:

1.定義委托。

2.將要進(jìn)行異步調(diào)用的方法“實(shí)例化”到定義的委托。

3.在委托上調(diào)用BeginInvoke方法。其中,BeginInvoke的參數(shù)由三個(gè)部分構(gòu)成。第一部分:所定義的委托的函數(shù)簽名。

第二部分:希望調(diào)用的回調(diào)函數(shù)的委托。第三部分:自定義委托的實(shí)例(該實(shí)例將會(huì)在回調(diào)函數(shù)中的IAsyncResult的AsyncRState屬性中重構(gòu)出我們?cè)诓襟E2中定義的委托實(shí)例,并借助這個(gè)實(shí)例來(lái)調(diào)用EndInvoke方法。)

4.如果我們希望在當(dāng)前線程來(lái)處理異步調(diào)用的結(jié)果,則可以使用BeginInvoke方法返回一個(gè)IAsyncResult實(shí)例(例如ar)

并在當(dāng)前線程等待。如果我們希望在異步線程中通過(guò)回調(diào)函數(shù)來(lái)處理結(jié)果,則我們需要在3中傳遞一個(gè)回調(diào)委托,并在該處理中調(diào)用EndInvoke方法。

以下是一段Programming C#(4版)中的一段實(shí)例:

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

namespace?property
{
????
public?class?DelegateClass
????{
????????
public?delegate?int?AsyncSampDelegate();
????????
public?event?AsyncSampDelegate?delEvent;

????????
public?void?Run()
????????{
????????????Console.WriteLine(
"The?Run?Thread?is?{0}",?Thread.CurrentThread.GetHashCode());
????????????
foreach?(AsyncSampDelegate?del?in?delEvent.GetInvocationList())
????????????{
????????????????del.BeginInvoke(
new?AsyncCallback(ReturnAsync),?del);
????????????}
????????}

????????
public?void?ReturnAsync(IAsyncResult?ar)
????????{
????????????
//獲得調(diào)用委托實(shí)例的引用
????????????AsyncSampDelegate?del?=?(AsyncSampDelegate)ar.AsyncState;
????????????
int?result?=?del.EndInvoke(ar);
????????????Console.WriteLine(
"The?result?is?{0},The?Thread?is?{1}",?result,?Thread.CurrentThread.GetHashCode());
????????}
????}

????
public?class?FirstSubscribe
????{
????????
private?int?myCount?=?0;

????????
public?void?AddFunToDel(DelegateClass?tmpDel)
????????{
????????????tmpDel.delEvent
+=new?DelegateClass.AsyncSampDelegate(FirstFun);
????????}


????????
public?int?FirstFun()
????????{
????????????
return?myCount++;
????????}
????}

????
public?class?SecondSubscribe
????{
????????
private?int?myCount?=?0;

????????
public?void?AddFunToDel(DelegateClass?tmpDel)
????????{
????????????tmpDel.delEvent
+=new?DelegateClass.AsyncSampDelegate(SecondFun);
????????}

????????
public?int?SecondFun()
????????{
????????????
return?myCount?+=?2;
????????}
????}

????
public?class?App
????{
????????
static?void?Main()
????????{
????????????DelegateClass?delClass?
=?new?DelegateClass();
????????????FirstSubscribe?fs?
=?new?FirstSubscribe();
????????????SecondSubscribe?ss?
=?new?SecondSubscribe();

????????????fs.AddFunToDel(delClass);
????????????ss.AddFunToDel(delClass);

????????????Console.WriteLine(
"The?Main?Thread?is?{0}",?Thread.CurrentThread.GetHashCode());
????????????delClass.Run();
????????????Console.Read();
????????}
????}
}?

?

?

?

多線程和異步操作的異同

  多線程和異步操作兩者都可以達(dá)到避免調(diào)用線程阻塞的目的,從而提高軟件的可響應(yīng)性。甚至有些時(shí)候我們就認(rèn)為多線程和異步操作是等同的概念。但是,多線程和異步操作還是有一些區(qū)別的。而這些區(qū)別造成了使用多線程和異步操作的時(shí)機(jī)的區(qū)別。

  異步操作的本質(zhì)

   所有的程序最終都會(huì)由計(jì)算機(jī)硬件來(lái)執(zhí)行,所以為了更好的理解異步操作的本質(zhì),我們有必要了解一下它的硬件基礎(chǔ)。 熟悉電腦硬件的朋友肯定對(duì)DMA這個(gè)詞不陌生,硬盤(pán)、光驅(qū)的技術(shù)規(guī)格中都有明確DMA的模式指標(biāo),其實(shí)網(wǎng)卡、聲卡、顯卡也是有DMA功能的。DMA就是直 接內(nèi)存訪問(wèn)的意思,也就是說(shuō),擁有DMA功能的硬件在和內(nèi)存進(jìn)行數(shù)據(jù)交換的時(shí)候可以不消耗CPU資源。只要CPU在發(fā)起數(shù)據(jù)傳輸時(shí)發(fā)送一個(gè)指令,硬件就開(kāi) 始自己和內(nèi)存交換數(shù)據(jù),在傳輸完成之后硬件會(huì)觸發(fā)一個(gè)中斷來(lái)通知操作完成。這些無(wú)須消耗CPU時(shí)間的I/O操作正是異步操作的硬件基礎(chǔ)。所以即使在DOS 這樣的單進(jìn)程(而且無(wú)線程概念)系統(tǒng)中也同樣可以發(fā)起異步的DMA操作。

  線程的本質(zhì)

  線程不是一個(gè)計(jì)算機(jī)硬件的功能,而是操作系統(tǒng)提供的一種邏輯功能,線程本質(zhì)上是進(jìn)程中一段并發(fā)運(yùn)行的代碼,所以線程需要操作系統(tǒng)投入CPU資源來(lái)運(yùn)行和調(diào)度。

  異步操作的優(yōu)缺點(diǎn)

   因?yàn)楫惒讲僮鳠o(wú)須額外的線程負(fù)擔(dān),并且使用回調(diào)的方式進(jìn)行處理,在設(shè)計(jì)良好的情況下,處理函數(shù)可以不必使用共享變量(即使無(wú)法完全不用,最起碼可以減少 共享變量的數(shù)量),減少了死鎖的可能。當(dāng)然異步操作也并非完美無(wú)暇。編寫(xiě)異步操作的復(fù)雜程度較高,程序主要使用回調(diào)方式進(jìn)行處理,與普通人的思維方式有些 初入,而且難以調(diào)試。

  多線程的優(yōu)缺點(diǎn)

  多線程的優(yōu)點(diǎn)很明顯,線程中的處理程序依然是順序執(zhí)行,符合普通人的思維習(xí)慣,所以編程簡(jiǎn)單。但是多線程的缺點(diǎn)也同樣明顯,線程的使用(濫用)會(huì)給系統(tǒng)帶來(lái)上下文切換的額外負(fù)擔(dān)。并且線程間的共享變量可能造成死鎖的出現(xiàn)。

  適用范圍

   在了解了線程與異步操作各自的優(yōu)缺點(diǎn)之后,我們可以來(lái)探討一下線程和異步的合理用途。我認(rèn)為:當(dāng)需要執(zhí)行I/O操作時(shí),使用異步操作比使用線程+同步 I/O操作更合適。I/O操作不僅包括了直接的文件、網(wǎng)絡(luò)的讀寫(xiě),還包括數(shù)據(jù)庫(kù)操作、Web Service、HttpRequest以及.net Remoting等跨進(jìn)程的調(diào)用。

  而線程的適用范圍則是那種需要長(zhǎng)時(shí)間CPU運(yùn)算的場(chǎng)合,例如耗時(shí)較長(zhǎng)的圖形處理和算法執(zhí)行。但是往 往由于使用線程編程的簡(jiǎn)單和符合習(xí)慣,所以很多朋友往往會(huì)使用線程來(lái)執(zhí)行耗時(shí)較長(zhǎng)的I/O操作。這樣在只有少數(shù)幾個(gè)并發(fā)操作的時(shí)候還無(wú)傷大雅,如果需要處 理大量的并發(fā)操作時(shí)就不合適了。

  實(shí)例研究

  說(shuō)了那么理論上的東西,可能有些兄弟早就不耐煩了,現(xiàn)在我們來(lái)研究幾個(gè)實(shí)際的異步操作例子吧。

  實(shí)例1:由delegate產(chǎn)生的異步方法到底是怎么回事?

  大家可能都知道,使用delegate可以“自動(dòng)”使一個(gè)方法可以進(jìn)行異步的調(diào)用。從直覺(jué)上來(lái)說(shuō),我覺(jué)得是由編譯器或者CLR使用了另外的線程來(lái)執(zhí)行目標(biāo)方法。到底是不是這樣呢?讓我們來(lái)用一段代碼證明一下吧。

?

Code
using?System;
using?System.Threading;

namespace?AsyncDelegateDemo
{
??
delegate?void?AsyncFoo(int?i);
??
class?Program
??{
????
///?<summary>
????
///?輸出當(dāng)前線程的信息
????
///?</summary>
???
///?<param?name="name">方法名稱</param>

????
static?void?PrintCurrThreadInfo(string?name)
????{
??????Console.WriteLine(
"Thread?Id?of?"?+?name+?"?is:?"?+?Thread.CurrentThread.ManagedThreadId+?",?current?thread?is?"
??????
+?(Thread.CurrentThread.IsThreadPoolThread???""?:?"not?")
??????
+?"thread?pool?thread.");
????}

????
///?<summary>
????
///?測(cè)試方法,Sleep一定時(shí)間
????
///?</summary>
????
///?<param?name="i">Sleep的時(shí)間</param>
????static?void?Foo(int?i)
????{
???????PrintCurrThreadInfo(
"Foo()");
???????Thread.Sleep(i);
????}

????
///?<summary>
????
///?投遞一個(gè)異步調(diào)用
????
///?</summary>
????static?void?PostAsync()
????{
??????AsyncFoo?caller?
=?new?AsyncFoo(Foo);
??????caller.BeginInvoke(
1000,?new?AsyncCallback(FooCallBack),?caller);
????}

????
static?void?Main(string[]?args)
????{
??????PrintCurrThreadInfo(
"Main()");
??????
for(int?i?=?0;?i?<?10?;?i++)
??????{
?????????PostAsync();
??????}
??????Console.ReadLine();
????}

????
static?void?FooCallBack(IAsyncResult?ar)
????{
??????PrintCurrThreadInfo(
"FooCallBack()");
??????AsyncFoo?caller?
=?(AsyncFoo)?ar.AsyncState;
??????caller.EndInvoke(ar);
????}
??}
}?

這段代碼代碼的輸出如下:


Thread Id of Main() is: 1, current thread is not thread pool thread.

Thread Id of Foo() is: 3, current thread is thread pool thread.

Thread Id of FooCallBack() is: 3, current thread is thread pool thread.

Thread Id of Foo() is: 3, current thread is thread pool thread.

Thread Id of Foo() is: 4, current thread is thread pool thread.

Thread Id of Foo() is: 5, current thread is thread pool thread.

Thread Id of FooCallBack() is: 3, current thread is thread pool thread.

Thread Id of Foo() is: 3,

?

?///

http://www.cnsdn.com.cn/blog/article.asp?id=2164

///

?

  。NET?Framework?為異步操作提供了兩種設(shè)計(jì)模式:使用?IAsyncResult?對(duì)象的異步操作與使用事件的異步操作。先來(lái)學(xué)習(xí)前者

  概述

  IAsyncResult?異步設(shè)計(jì)模式通過(guò)名為?BeginOperationName?和?EndOperationName?的兩個(gè)方法來(lái)實(shí)現(xiàn)原同步方法的異步調(diào)用,如?FileStream?類提供了?BeginRead?和?EndRead?方法來(lái)從文件異步讀取字節(jié),它們是?Read?方法的異步版本

  Begin?方法包含同步方法簽名中的任何參數(shù),此外還包含另外兩個(gè)參數(shù):一個(gè)AsyncCallback?委托和一個(gè)用戶定義的狀態(tài)對(duì)象。委托用來(lái)調(diào)用回調(diào)方法,狀態(tài)對(duì)象是用來(lái)向回調(diào)方法傳遞狀態(tài)信息。該方法返回一個(gè)實(shí)現(xiàn)?IAsyncResult?接口的對(duì)象

  End?方法用于結(jié)束異步操作并返回結(jié)果,因此包含同步方法簽名中的?ref?和?out?參數(shù),返回值類型也與同步方法相同。該方法還包括一個(gè)?IAsyncResult?參數(shù),用于獲取異步操作是否完成的信息,當(dāng)然在使用時(shí)就必須傳入對(duì)應(yīng)的?Begin?方法返回的對(duì)象實(shí)例

  開(kāi)始異步操作后如果要阻止應(yīng)用程序,可以直接調(diào)用?End?方法,這會(huì)阻止應(yīng)用程序直到異步操作完成后再繼續(xù)執(zhí)行。也可以使用?IAsyncResult?的?AsyncWaitHandle?屬性,調(diào)用其中的WaitOne等方法來(lái)阻塞線程。這兩種方法的區(qū)別不大,只是前者必須一直等待而后者可以設(shè)置等待超時(shí)

  如果不阻止應(yīng)用程序,則可以通過(guò)輪循?IAsyncResult?的?IsCompleted?狀態(tài)來(lái)判斷操作是否完成,或使用?AsyncCallback?委托來(lái)結(jié)束異步操作。AsyncCallback?委托包含一個(gè)?IAsyncResult?的簽名,回調(diào)方法內(nèi)部再調(diào)用?End?方法來(lái)獲取操作執(zhí)行結(jié)果

  嘗試

  先來(lái)熟悉一下今天的主角,IAsyncResult?接口

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


  我用一個(gè)?AsyncDemo?類作為異步方法的提供者,后面的程序都會(huì)調(diào)用它。內(nèi)部很簡(jiǎn)單,構(gòu)造函數(shù)接收一個(gè)字符串作為?name?,Run?方法輸出?"My?name?is?"?+?name?,而異步方法直接用委托的?BeginInvoke?和?EndInvoke?方法實(shí)現(xiàn)

public?class?AsyncDemo
{
//?Use?in?asynchronous?methods
private?delegate?string?runDelegate();
private?string?m_Name;
private?runDelegate?m_Delegate;
public?AsyncDemo(string?name)
{
m_Name?=?name;
m_Delegate?=?new?runDelegate(Run);
}
/**
///?Synchronous?method
///
///
public?string?Run()
{
return?"My?name?is?"?+?m_Name;
}
/**
///?Asynchronous?begin?method
///
///
///
///
public?IAsyncResult?BeginRun(AsyncCallback?callBack,?Object?stateObject)
{
try
{
return?m_Delegate.BeginInvoke(callBack,?stateObject);
}
catch(Exception?e)
{
//?Hide?inside?method?invoking?stack
throw?e;
}
}
/**
///?Asynchronous?end?method
///
///
///
public?string?EndRun(IAsyncResult?ar)
{
if?(ar?==?null)
throw?new?NullReferenceException("Arggument?ar?can't?be?null");
try
{
return?m_Delegate.EndInvoke(ar);
}
catch?(Exception?e)
{
//?Hide?inside?method?invoking?stack
throw?e;
}
}
????????????}?
?


  首先是?Begin?之后直接調(diào)用?End?方法,當(dāng)然中間也可以做其他的操作

class?AsyncTest
{
static?void?Main(string[]?args)
{
AsyncDemo?demo?=?new?AsyncDemo("jiangnii");
//?Execute?begin?method
IAsyncResult?ar?=?demo.BeginRun(null,?null);
//?You?can?do?other?things?here
//?Use?end?method?to?block?thread?until?the?operation?is?complete
string?demoName?=?demo.EndRun(ar);
Console.WriteLine(demoName);
}
????????????}?
?


  也可以用?IAsyncResult?的?AsyncWaitHandle?屬性,我在這里設(shè)置為1秒超時(shí)

class?AsyncTest
{
static?void?Main(string[]?args)
{
AsyncDemo?demo?=?new?AsyncDemo("jiangnii");
//?Execute?begin?method
IAsyncResult?ar?=?demo.BeginRun(null,?null);
//?You?can?do?other?things?here
//?Use?AsyncWaitHandle.WaitOne?method?to?block?thread?for?1?second?at?most
ar.AsyncWaitHandle.WaitOne(1000,?false);
if?(ar.IsCompleted)
{
//?Still?need?use?end?method?to?get?result,?
//?but?this?time?it?will?return?immediately
string?demoName?=?demo.EndRun(ar);
Console.WriteLine(demoName);
}
else
{
Console.WriteLine("Sorry,?can't?get?demoName,?the?time?is?over");
}
}
????????????}?
?


  不中斷的輪循,每次循環(huán)輸出一個(gè)?"."

class?AsyncTest
{
static?void?Main(string[]?args)
{
AsyncDemo?demo?=?new?AsyncDemo("jiangnii");
//?Execute?begin?method
IAsyncResult?ar?=?demo.BeginRun(null,?null);
Console.Write("Waiting..");
while?(!ar.IsCompleted)
{
Console.Write(".");
//?You?can?do?other?things?here
}
Console.WriteLine();
//?Still?need?use?end?method?to?get?result,?
//?but?this?time?it?will?return?immediately
string?demoName?=?demo.EndRun(ar);
Console.WriteLine(demoName);
}
????????????}?
?


  最后是使用回調(diào)方法并加上狀態(tài)對(duì)象,狀態(tài)對(duì)象被作為?IAsyncResult?參數(shù)的?AsyncState?屬性被傳給回調(diào)方法。回調(diào)方法執(zhí)行前不能讓主線程退出,我這里只是簡(jiǎn)單的讓其休眠了1秒。另一個(gè)與之前不同的地方是?AsyncDemo?對(duì)象被定義成了類的靜態(tài)字段,以便回調(diào)方法使用

?class?AsyncTest
{
static?AsyncDemo?demo?=?new?AsyncDemo("jiangnii");
static?void?Main(string[]?args)
{
//?State?object
bool?state?=?false;
//?Execute?begin?method
IAsyncResult?ar?=?demo.BeginRun(new?AsyncCallback(outPut),?state);
//?You?can?do?other?thins?here
//?Wait?until?callback?finished
System.Threading.Thread.Sleep(1000);
}
//?Callback?method
static?void?outPut(IAsyncResult?ar)
{
bool?state?=?(bool)ar.AsyncState;
string?demoName?=?demo.EndRun(ar);
if?(state)
{
Console.WriteLine(demoName);
}
else
{
Console.WriteLine(demoName?+?",?isn't?it?");
}
}
????????????}?
?


  其他

  對(duì)于一個(gè)已經(jīng)實(shí)現(xiàn)了?BeginOperationName?和?EndOperationName?方法的對(duì)象,我們可以直接用上述方式調(diào)用,但對(duì)于只有同步方法的對(duì)象,我們要對(duì)其進(jìn)行異步調(diào)用也不需要增加對(duì)應(yīng)的異步方法,而只需定義一個(gè)委托并使用其?BeginInvoke?和?EndInvoke?方法就可以了

?

轉(zhuǎn)載于:https://www.cnblogs.com/ruyi/archive/2009/07/14/1523510.html

總結(jié)

以上是生活随笔為你收集整理的[转] C#异步操作的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。