欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
什么是.Net的異步機制(Invoke,BeginInvoke,EndInvoke) - ...

什么是.Net的異步機制(Invoke,BeginInvoke,EndInvoke) - step 2

 

上一篇文章(什么是.Net的異步機制(委托Delegate) - step 1),我已經(jīng)解釋了什么是異步編程,那么現在我們就開(kāi)始具體的說(shuō)怎樣異步編程.

 

我們怎樣進(jìn)行異步編程/開(kāi)發(fā)?

 

現在擴充下上篇文章的類(lèi)(AsyncTest),提供更多的例子并從中做下簡(jiǎn)單的對比, 從新的認識下異步的內部機制,下面我們增加一個(gè)新的委托

1,我們添加一個(gè)新方法(計算年薪YearlySalary)

public decimal YearlySalary(decimal salary, int monthCount, decimal bonus);

2,為這個(gè)方法增加異步的功能,這樣我們仍然使用委托(Delegate)

public delegate decimal SalaryEventHandler(decimal salary, int monthCount, decimal bonus);

 

經(jīng)過(guò)簡(jiǎn)單修改后,下面是我們新的AsyncTest類(lèi)

Code1

 1
//我們使用委托來(lái)提供.Net的異步機制
 2
public delegate string AsyncEventHandler(string name); // 對應Hello 方法
 3
public delegate decimal SalaryEventHandler(decimal salary, int monthCount, decimal bonus); // 對應YearlySalary方法
 4
public class AsyncTest
 5
{
 6
    
public string Hello(string name)
 7
    
{
 8
        
return "Hello:" + name;
 9
    }

10

11
    
/// <summary>
12
    
/// 計算一年的薪水
13
    
/// </summary>
14
    
/// <param name="salary">月薪</param>
15
    
/// <param name="monthCount">一年支付月數量</param>
16
    
/// <param name="bonus">獎金</param>
17
    
/// <returns></returns>

18
    public decimal YearlySalary(decimal salary, int monthCount, decimal bonus)
19
    
{
20
        
//添加輔助方法,查看當前的線(xiàn)程ID
21
        Console.WriteLine("Thread ID:#{0}", Thread.CurrentThread.ManagedThreadId);
22

23
        
return salary * monthCount + bonus;
24
    }

25
}

 

這里用.NET Reflector 5 來(lái)反編譯,之所以用這個(gè),因為比微軟的會(huì )更加清晰明了.如果想了解這個(gè)工具的朋友可查看(http://reflector.red-gate.com/)


1

開(kāi)始我先對圖1中的小圖標進(jìn)行個(gè)簡(jiǎn)單的解釋

 = 類(lèi)(Class)   
=
類(lèi)繼承的基類(lèi) 
= sealed(委托)

 = 類(lèi)的構造函數 
=
方法 
virtual方法

 

下面我們先比較下SalaryEventHandler AsyncEventHandler委托的異同.

1)      SalaryEventHandler

public delegate decimal SalaryEventHandler(decimal salary, int monthCount, decimal bonus);


2.1

編譯器生成的類(lèi)Code2.1(2.1)
Code 2.1

 1
    public sealed class SalaryEventHandler : MulticastDelegate
 2
    
{
 3
        
public SalaryEventHandler(object @object, IntPtr method)
 4
        
{
.}

 5
        
public virtual IAsyncResult BeginInvoke(decimal salary, int monthCount, decimal bonus,
 AsyncCallback callback, 
object @object)
 6
        
{
}

 7
        
public virtual decimal EndInvoke(IAsyncResult result)
 8
        
{
}

 9
        
public virtual decimal Invoke(decimal salary, int monthCount, decimal bonus)
10
        
{
}

11
    }

2)      AsyncEventHandler

public delegate string AsyncEventHandler(string name);


2.2

編譯器生成的類(lèi)Code2.2(2.2)

Code2.2

 1
    public sealed class AsyncEventHandler : MulticastDelegate
 2
    
{
 3
        
public AsyncEventHandler(object @object, IntPtr method)
 4
        
{
.}

 5
        
public virtual IAsyncResult BeginInvoke(string name, AsyncCallback callback, object @object)
 6
        
{
}

 7
        
public virtual string EndInvoke(IAsyncResult result)
 8
        
{
}

 9
        
public virtual string Invoke(string name)
10
        
{
}

11
    }

 

對比兩個(gè)委托(事實(shí)上是一個(gè)sealed 的類(lèi)),都繼承于System.MuliticaseDelegate, 三個(gè)virtual Invoke / BeginInvoke / EndInvoke 方法.

//同步方法

Invoke : 參數的個(gè)數,類(lèi)型, 返回值都不相同

 

 

//異步方法,作為一組來(lái)說(shuō)明

BeginInvoke : 參數的個(gè)數和類(lèi)型不同,返回值相同

EndInvoke : 參數相同,返回值不同

 

這里我們先介紹下 Invoke這個(gè)方法, 我們用SalaryEventHandler委托為例(直接調用Code 1 的類(lèi))

Code 3

 1
class Program
 2
{
 3
    
static void Main(string[] args)
 4
    
{
 5
        
//添加輔助方法,查看當前的線(xiàn)程ID
 6
        Console.WriteLine("Main Thread ID:#{0}", Thread.CurrentThread.ManagedThreadId);
 7

 8
        AsyncTest test 
= new AsyncTest();
 9
        
//[1],我們習慣的調用方式
10
        decimal v1 = test.YearlySalary(10000015100000);
11
        
//使用委托調用
12
        SalaryEventHandler salaryDelegate = test.YearlySalary;
13
        
//[2],編譯器會(huì )自動(dòng)的把[2]轉變成[3]Invoke的調用方式,[2]和[3]是完全相同的
14
        decimal v2 = salaryDelegate(10000015100000);
15
        
//[3]
16
        decimal v3 = salaryDelegate.Invoke(10000015100000);
17

18
        Console.WriteLine(
"V1:{0},V2:{1},V3:{2}", v1, v2, v3);
19
        Console.ReadLine(); 
// 讓黑屏等待,不會(huì )直接關(guān)閉..
20
    }

21
}

輸出的結果


3

從結果可以看出,他們是同一個(gè)線(xiàn)程調用的(都是#10).這就說(shuō)明[1],[2],[3]是同步調用

[2],[3]對比[1], 只不過(guò)[2],[3]是通過(guò)委托的方式(其實(shí)我們可以說(shuō)成“通過(guò)代理的方式完成”),[1]是直接的調用.舉一個(gè)我們平常生活中例子:買(mǎi)機票,我們到代理點(diǎn)購買(mǎi)機票而不是直接跑到機場(chǎng)購買(mǎi),就好像我們叫別人幫我們買(mǎi)機票一樣,最后到手的機票是一樣的, SalaryEventHandler就是我們的代理點(diǎn).所以用代理的方式還是直接調用的方式,他們提供的參數和返回值必須是一樣的.

 

接下來(lái)我們開(kāi)始講異步機制核心的兩個(gè)方法BeginInvoke/EndInvoke,他們作為一個(gè)整體來(lái)完成Invoke方法的調用,不同于Inoke方法的是他們是異步執行(另外開(kāi)一個(gè)線(xiàn)程執行),下面先解釋下他們的作用

BeginInvoke : 開(kāi)始一個(gè)異步的請求,調用線(xiàn)程池中一個(gè)線(xiàn)程來(lái)執行
EndInvoke : 完成異步的調用, 處理返回值 異常錯誤.

注意: BeginInvokeEndInvoke必須成對調用.即使不需要返回值,但EndInvoke還是必須調用,否則可能會(huì )造成內存泄漏.


我們來(lái)對比下 SalaryEventHandler AsyncEventHandler委托反編譯BeginInoke后的異同.

SalaryEventHandler 委托:

public virtual IAsyncResult BeginInvoke(decimal salary, int monthCount, decimal bonus, AsyncCallback callback, object @object)

AsyncEventHandler 委托:

public virtual IAsyncResult BeginInvoke(string name, AsyncCallback callback, object @object)

 

可以看出參數的個(gè)數和類(lèi)型是不同的,我們把焦點(diǎn)放到他們的相同點(diǎn)上,

1,返回值是相同的: 返回IAsyncResult 對象(異步的核心). IAsyncResult是什么呢? 簡(jiǎn)單的說(shuō),存儲異步操作的狀態(tài)信息的一個(gè)接口,也可以用他來(lái)結束當前異步.具體的可以看下 http://msdn.microsoft.com/zh-cn/library/system.iasyncresult(VS.80).aspx

 

2,編譯器會(huì )根據委托的參數個(gè)數和類(lèi)型生成相應的BeginInvoke方法,只有最后兩個(gè)參數是永遠相同的,他提供一個(gè)AsyncCallback 委托(public delegate void AsyncCallback(IAsyncResult ar);) 和一個(gè) Object 對象.

 

我們再來(lái)看看EndInvoke的異同.

SalaryEventHandler 委托:

public virtual decimal EndInvoke(IAsyncResult result)

AsyncEventHandler 委托:

public virtual string EndInvoke(IAsyncResult result)

 

EndInvoke的參數是一樣的, 唯一是在是返回值不同(他們會(huì )根據自己委托的返回值類(lèi)型生成自己的類(lèi)型)

 

,下面我會(huì )通過(guò)例子來(lái)說(shuō)明BeginInvoke/EndInvoke,還是使用SalaryEventHandler委托為例(直接調用Code 1 的類(lèi))

 

.Net Framework 提供了兩種方式來(lái)使用異步方法

第一種: 通過(guò)IAsyncResult 對象

Code 4.1

 1
class Program
 2
{
 3
    
static IAsyncResult asyncResult;
 4

 5
    
static void Main(string[] args)
 6
    
{
 7

 8
        AsyncTest test 
= new AsyncTest();
 9
        SalaryEventHandler dele 
= test.YearlySalary;
10
        
//異步方法開(kāi)始執行,返回IAsyncResult(存儲異常操作的狀態(tài)信息) 接口,同時(shí)EndInvoke 方法也需要他來(lái)作為參數來(lái)結束異步調用
11
        asyncResult = dele.BeginInvoke(10000015100000nullnull);
12
        
//獲取返回值
13
        decimal val = GetResult();
14
        Console.WriteLine(val);
15
        Console.ReadLine(); 
// 讓黑屏等待,不會(huì )直接關(guān)閉..
16
    }

17

18
    
static decimal GetResult()
19
    
{
20
        
decimal val = 0;
21
        
//獲取原始的委托對象:先是獲取AsyncResult對象,再根據他的AsyncDelegate屬性來(lái)調用
當前的(那一個(gè))委托對象
22
        AsyncResult result = (AsyncResult)asyncResult;
23
        SalaryEventHandler salDel 
= (SalaryEventHandler)result.AsyncDelegate;
24

25
        
//調用EndInvoke獲取返回值
26
        val = salDel.EndInvoke(asyncResult);
27

28
        
return val;
29
    }

30
}

第二種: 通過(guò)回調函數. 使用倒數第二個(gè)參數AsyncCallback 委托(public delegate void AsyncCallback(IAsyncResult ar);) ,建議使用這種方法.

Code 4.2

 1
class Program
 2
{
 3
    
static void Main(string[] args)
 4
    
{
 5
        AsyncTest test 
= new AsyncTest();
 6
        SalaryEventHandler dele 
= test.YearlySalary;
 7

 8
        
//異步方法開(kāi)始執行,使用BeginInvoke 倒數第二個(gè)參數(AsyncCallback委托對象) ,而不用返回值
 9
        dele.BeginInvoke(10000015100000, GetResultCallBack, null);
10
        
//和上面相同的
11
        
//AsyncCallback callback = new AsyncCallback(GetResultCallBack);
12
        
//dele.BeginInvoke(100000, 15, 100000, callback, null);
13

14
        Console.ReadLine(); 
// 讓黑屏等待,不會(huì )直接關(guān)閉..
15
    }

16

17
    
//必須遵循AsyncCallback 委托的定義:返回值為空,一個(gè)IAsyncResult對象參數
18
    static void GetResultCallBack(IAsyncResult asyncResult)
19
    
{
20
        
decimal val = 0;
21
        
//獲取原始的委托對象
22
        AsyncResult result = (AsyncResult)asyncResult;
23
        SalaryEventHandler salDel 
= (SalaryEventHandler)result.AsyncDelegate;
24

25
        
//調用EndInvoke獲取返回值
26
        val = salDel.EndInvoke(asyncResult);
27

28
        Console.WriteLine(val);
29
    }

30
}

 

BeginInvoke最后一個(gè)參數是做什么的呢?我把Code 4.2 方法修改下.

Code 4.3

 1
class Program
 2
{
 3
    
static void Main(string[] args)
 4
    
{
 5
        AsyncTest test 
= new AsyncTest();
 6
        SalaryEventHandler dele 
= test.YearlySalary;
 7

 8
        
//異步方法開(kāi)始執行,看最后一個(gè)參數(Object對象) [Note1:],這里我們傳遞2000(int)
 9
        dele.BeginInvoke(10000015100000, GetResultCallBack, 2000);
10

11
        Console.ReadLine(); 
// 讓黑屏等待,不會(huì )直接關(guān)閉..
12
    }

13

14
    
static void GetResultCallBack(IAsyncResult asyncResult)
15
    
{
16
        
//[Note1:],他的作用就是來(lái) "傳遞額外的參數",因為他本身是Object對象,我們可以傳遞任何對象
17
        int para = (int)asyncResult.AsyncState;
18
        Console.WriteLine(para);//輸出:2000
19
    }

20
}

 

異步的異常處理

接下來(lái)再講講EndInvoke,獲取最后的返回值之外,他的一個(gè)重要的應用在引發(fā)異常來(lái)從異步操作返回異常

Code 5

 1
class Program
 2
{
 3
    
static void Main(string[] args)
 4
    
{
 5
        AsyncTest test 
= new AsyncTest();
 6
        SalaryEventHandler dele 
= test.YearlySalary;
 7

 8
        dele.BeginInvoke(
10000015100000, GetResultCallBack, null);
 9
        Console.ReadLine(); 
// 讓黑屏等待,不會(huì )直接關(guān)閉..
10
    }

11

12
    
static void GetResultCallBack(IAsyncResult asyncResult)
13
    
{
14
        
decimal val = 0;
15
        
//獲取原始的委托對象
16
        AsyncResult result = (AsyncResult)asyncResult;
17
        SalaryEventHandler salDel 
= (SalaryEventHandler)result.AsyncDelegate;
18
        
try
19
        
{
20
            
//如果EndInvoke發(fā)生異常,會(huì )在EndInvoke得到原始的異常.
21
            val = salDel.EndInvoke(asyncResult);
22
            Console.WriteLine(val);
23
        }

24
        
catch (Exception ex)
25
        
{
26
            Console.WriteLine(ex.Message);
27
        }

28
    }

29
}

30
public delegate decimal SalaryEventHandler(decimal salary, int monthCount, decimal bonus); // 對應YearlySalary方法
31
public class AsyncTest
32
{
33
    
public decimal YearlySalary(decimal salary, int monthCount, decimal bonus)
34
    
{
35
        
throw new Exception("error"); //引發(fā)異常
36
        return salary * monthCount + bonus;
37
    }

38
}

 

我們主動(dòng)在YearlySalary方法中引發(fā)異常,BeginInvoke開(kāi)始異步調用的時(shí)候捕獲到了這個(gè)異常,.Net Framework會(huì )在EndInvoke得到原始的異常.

 

說(shuō)到這里,大家是否可以簡(jiǎn)單的應用委托來(lái)開(kāi)始自己的異步操作呢? 下面看看我是怎樣為我自己的類(lèi)添加異步的.

1, 類(lèi)的定義,需要遵循.Net Framework 的規則

1)同步和異步是同時(shí)并存的

2)從最上面的兩個(gè)委托SalaryEventHandler AsyncEventHandler生成的BeginInvoke / EndInvoke 對比中看出,我們也來(lái)定義我們自己的異步方法,我們遵循微軟設計師異步方法設計的規則,Begin+同步方法名 / End+同步方法名

BeginXXX 必須返回IAsyncResult對象,后兩位參數必須為AsyncCallback callback, object state,前面的參數和同步方法的參數一樣

EndXXX 參數必須為IAsyncResult對象,返回值為同步方法的返回值

 

Code 6.1

 1
public class AsyncTest
 2
{
 3
    
private delegate string AsyncEventHandler(string name);
 4
    
private AsyncEventHandler _Async;
 5
    
public string Hello(string name)
 6
    
{
 7
        
return "Hello:" + name;
 8
    }

 9

10
    
//按照.Net Framework的規則 ,編寫(xiě)我們自己的BeginInvoke方法
11
    public virtual IAsyncResult BeginHello(string name, AsyncCallback callback, object state)
12
    
{
13
        AsyncEventHandler del 
= Hello;
14

15
        
this._Async = del;
16

17
        
return del.BeginInvoke(name, callback, state);
18
    }

19
    
//編寫(xiě)我們自己的EndInvoke方法
20
    public virtual string EndHello(IAsyncResult asyncResult)
21
    
{
22
        
if (asyncResult == null)
23
            
throw new ArgumentNullException("asyncResult");
24
        
if (this._Async == null)
25
            
throw new ArgumentException("_Async");
26

27
        
string val = string.Empty;
28
        
try
29
        
{
30
            val 
= this._Async.EndInvoke(asyncResult);
31
        }

32
        
finally
33
        
{
34
            
this._Async = null;
35
        }

36
        
return val;
37
    }

38
}

 

2: 調用我們編寫(xiě)的類(lèi)

Code 6.2

 1
class Program
 2
{
 3
    
static void Main(string[] args)
 4
    
{
 5
        AsyncTest test 
= new AsyncTest();
 6
        
//使用回調函數,就是上面提到的"第二種"
 7
        AsyncCallback callback = new AsyncCallback(OnHelloCallback);
 8
        test.BeginHello(
"Andy Huang", callback, test);
 9
        
//和上面一樣
10
        
//IAsyncResult result = test.BeginHello("Andy Huang", OnHelloCallback, test);
11

12
        Console.ReadLine(); 
// 讓黑屏等待,不會(huì )直接關(guān)閉..
13
    }

14

15
    
static void OnHelloCallback(IAsyncResult asyncResult)
16
    
{
17
        
//獲取額外的參數
18
        AsyncTest obj = (AsyncTest)asyncResult.AsyncState;
19
        
string val = obj.EndHello(asyncResult);
20
        Console.WriteLine(val);
21
    }

22
}

 

:Hello的方法的異步重構在下面的代碼中可以下載到.

 

下一篇中我們會(huì )說(shuō)說(shuō)異步中的一些高級應用,異步的核心,還有微軟.Net Framework 為我們提供的各種類(lèi)中(具有異步方法的類(lèi)),我們是怎么使用這些方法的.最后要提醒下大家:濫用異步,會(huì )影響性能,而且增加編程難度


以上有word 文檔直接粘貼,排版可能不太看,你可以通過(guò)下面來(lái)下載相應的代碼/文檔

1,文檔

2,代碼 (VS2008開(kāi)發(fā),.Net Framework 2.0(C Sharp)編寫(xiě))

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
C#線(xiàn)程系列講座(1):BeginInvoke和EndInvoke方法
多線(xiàn)程(一):異步委托
關(guān)于.NET異步調用的初步總結
深入APM,實(shí)現自己的APM
C#異步調用的好處和方法
C#同步方法和異步方法的區別
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久