Asynchronous Programming Model
整个异步调用过程中都是围绕IAsyncResult来进行的,大家可以看看上篇文章的例子,BeginXXX 返回这个对象,EndXXX接收这个对象来结束当前异步对象,下面我们来看看IAsyncResult 接口成员/和实现此接口的AsyncResult类成员(其中有些在上篇中已经涉及到)
IAsyncResult接口
1
public
interface
IAsyncResult
2
![](http://img.e-com-net.com/image/product/8bf85857a9e14d23a651e7c8ef856bcc.gif)
{
3![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
WaitHandle AsyncWaitHandle
{ get; } //阻塞一个线程,直到一个或多个同步对象接收到信号
4![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
Boolean IsCompleted
{ get; } //判读当前异步是否完成
5![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
Object AsyncState
{ get; } //获取额外的参数值,请看上一篇文章的Code 4.3
6![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
Boolean CompletedSynchronously
{ get; } //几乎没有使用
7
}
AsyncResult类
1
public
class
AsyncResult : IAsyncResult, IMessageSink
2
![](http://img.e-com-net.com/image/product/8bf85857a9e14d23a651e7c8ef856bcc.gif)
{
3
//IAsyncResult 的实现
4![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
public virtual WaitHandle AsyncWaitHandle
{ get; }
5![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
public virtual bool IsCompleted
{ get; }
6![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
public virtual object AsyncState
{ get; }
7![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
public virtual bool CompletedSynchronously
{ get; }
8![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
9
// 其他一些重要的属性
10![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
public bool EndInvokeCalled
{ get; set; } //检验是否调用了EndInvoke()
11![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
public virtual object AsyncDelegate
{ get; } //获取原始的委托对象,可查看上一篇文章中的Code 4.1/4.2/5
12
}
注意:基本上都是只读属性
下面我们来看看异步的执行顺序,并回顾下 IAsyncResult 下各个属性的应用,如果还是不熟悉请看前2篇文章.
Code 1:
1
class
Program
2
![](http://img.e-com-net.com/image/product/8bf85857a9e14d23a651e7c8ef856bcc.gif)
{
3
static void Main(string[] args)
4![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
5
Console.WriteLine("[(#{1}){0}]:Asynchronous Start", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
6![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
7
AsyncTest test = new AsyncTest();
8
MyThirdAsyncCode.AsyncTest.SalaryEventHandler del = test.YearlySalary;
9
//使用回调函数
10
AsyncCallback callback = new AsyncCallback(OnSalaryCallback);
11
IAsyncResult ar = del.BeginInvoke(100000, 15, 100000, callback, 2000);
12![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
13
DoAntherJob();
14
Console.ReadLine(); // 让黑屏等待,不会直接关闭..
15
}
16![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
17
//开始其他工作.
18
static void DoAntherJob()
19![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
20
Thread.Sleep(1000);//需要1秒才能完成这个工作,注1
21
Console.WriteLine("[(#{1}){0}]:Do Another Job", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
22
}
23![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
24
static void OnSalaryCallback(IAsyncResult asyncResult)
25![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
26
//通过AsyncState 获取额外的参数.
27
decimal para = (int)asyncResult.AsyncState;
28![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
29
//通过AsyncDelegate 获取原始的委托对象
30
AsyncResult obj = (AsyncResult)asyncResult;
31
MyThirdAsyncCode.AsyncTest.SalaryEventHandler del =
(MyThirdAsyncCode.AsyncTest.SalaryEventHandler)obj.AsyncDelegate;
32![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
33
if (asyncResult.IsCompleted)// 判读是否已经调用完成
34
Console.WriteLine("[(#{1}){0}]:Asynchronous Finished.", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
35![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
36
decimal val = del.EndInvoke(asyncResult);
37![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
38
Console.WriteLine("[(#{2}){0}]:Output Result:{1}", DateTime.Now.ToString(), val + para, Thread.CurrentThread.ManagedThreadId);
39
}
40
}
41
![](http://img.e-com-net.com/image/product/46339e8aae704cb1a8b93e7cd90036c0.gif)
42
public
class
AsyncTest
43
![](http://img.e-com-net.com/image/product/8bf85857a9e14d23a651e7c8ef856bcc.gif)
{
44
public delegate decimal SalaryEventHandler(decimal salary, int monthCount, decimal bonus); // 对应YearlySalary方法
45
public decimal YearlySalary(decimal salary, int monthCount, decimal bonus)
46![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
47
//模拟耗时/复杂的逻辑计算.
48
Thread.Sleep(3000);//等待3秒,注2
49
return salary * monthCount + bonus;
50
}
51
}
![](http://img.e-com-net.com/image/product/453015aecb7541e38328ccc0730db3ee.png)
图1
我们看到DoAntherJob 比异步YearlySalary快2秒,看代码中(注1)和(注2),两个线程的执行结果
接下来,我们说说AsyncWaitHandle 属性. 他返回WaitHandle对象(System.Threading.WaitHandle), 他有3个重要的方法. WaitOne / WaitAny / WaitAll ,我们先来说下WaitOne,在Code1代码基础上只是增加了下面红色部分.
1,WaitOne
Code 1.1
IAsyncResult ar = del.BeginInvoke(100000, 15, 100000, callback, 2000);
//阻碍当前线程,直到异步调用结束.
ar.AsyncWaitHandle.WaitOne();
//开始其他工作.
DoAntherJob();
![](http://img.e-com-net.com/image/product/075eaaa0eecd47d0ad50d20bc85534d6.png)
图1.1
执行输出,对比图1我们可以看到执行的次序不一样了(看时间),调用WaitOne,会阻碍当前线程,直到异步完成,才释放当前的线程, WaitOne 提供了时间的重载版本WaitOne(int millisecondsTimeout)/ WaitOne(TimeSpan timeout);来判断阻碍的时间.无参的版本是无限等待的(直到异步调用结束)
2, WaitAll
我们在Code1的代码基础上加上Hello的异步调用(使Main提供多个异步调用),注意红色部分.
Code 1.2
1
class
Program
2
![](http://img.e-com-net.com/image/product/8bf85857a9e14d23a651e7c8ef856bcc.gif)
{
3
static void Main(string[] args)
4![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
5
Console.WriteLine("[(#{1}){0}]:Asynchronous Start", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
6![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
7
AsyncTest test = new AsyncTest();
8
MyThirdAsyncCode.AsyncTest.SalaryEventHandler del = test.YearlySalary;
9
MyThirdAsyncCode.AsyncTest.AsyncEventHandler asy = test.Hello;
10![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
11
IAsyncResult salayAsyc = del.BeginInvoke(100000, 15, 100000, OnSalaryCallback, null);
12
IAsyncResult helloAsyc = asy.BeginInvoke("Hello Andy", OnHelloCallback, null);
13
//把所有异步的句柄保存到WaitHandle 对象中
14![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
WaitHandle[] handles =
{ salayAsyc.AsyncWaitHandle, helloAsyc.AsyncWaitHandle };
15
//阻碍当前线程,直到所有异步调用结束.
16
WaitHandle.WaitAll(handles);
17![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
18
//开始其他工作.
19
DoAntherJob();
20
Console.ReadLine(); // 让黑屏等待,不会直接关闭..
21
}
22
static void DoAntherJob()
23![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
24
Thread.Sleep(1000);//需要1秒才能完成这个工作,注1
25
Console.WriteLine("[(#{1}){0}]:Do Another Job", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
26
}
27
static void OnSalaryCallback(IAsyncResult asyncResult)
28![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
29
//通过AsyncDelegate 获取原始的委托对象
30
AsyncResult obj = (AsyncResult)asyncResult;
31
MyThirdAsyncCode.AsyncTest.SalaryEventHandler del =
(MyThirdAsyncCode.AsyncTest.SalaryEventHandler)obj.AsyncDelegate;
32![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
33
if (asyncResult.IsCompleted)// 判读是否已经调用完成
34
Console.WriteLine("[(#{1}){0}]:Asynchronous Finished.", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
35![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
36
decimal val = del.EndInvoke(asyncResult);
37
Console.WriteLine("[(#{2}){0}]:Output Result:{1}", DateTime.Now.ToString(), val, Thread.CurrentThread.ManagedThreadId);
38
}
39![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
40
static void OnHelloCallback(IAsyncResult asyncResult)
41![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
42
//通过AsyncDelegate 获取原始的委托对象
43
AsyncResult obj = (AsyncResult)asyncResult;
44
MyThirdAsyncCode.AsyncTest.AsyncEventHandler del =
(MyThirdAsyncCode.AsyncTest.AsyncEventHandler)obj.AsyncDelegate;
45![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
46
if (asyncResult.IsCompleted)// 判读是否已经调用完成
47
Console.WriteLine("[(#{1}){0}]:Asynchronous Finished.", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId);
48![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
49
string val = del.EndInvoke(asyncResult);
50
Console.WriteLine("[(#{2}){0}]:Output Result:{1}", DateTime.Now.ToString(), val, Thread.CurrentThread.ManagedThreadId);
51
}
52
}
53
![](http://img.e-com-net.com/image/product/46339e8aae704cb1a8b93e7cd90036c0.gif)
54
public
class
AsyncTest
55
![](http://img.e-com-net.com/image/product/8bf85857a9e14d23a651e7c8ef856bcc.gif)
{
56
public delegate decimal SalaryEventHandler(decimal salary, int monthCount, decimal bonus); // 对应YearlySalary方法
57
public delegate string AsyncEventHandler(string name); // 对应Hello 方法
58
public string Hello(string name)
59![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
60
//模拟耗时/复杂的逻辑计算.等待5秒
61
Thread.Sleep(5000);
62
return "Hello:" + name;
63
}
64
public decimal YearlySalary(decimal salary, int monthCount, decimal bonus)
65![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
66
//模拟耗时/复杂的逻辑计算.
67
Thread.Sleep(3000);//等待3秒
68
return salary * monthCount + bonus;
69
}
70
}
![](http://img.e-com-net.com/image/product/0bf6afd9aa5f49abb166f1902ff5aaab.png)
图1.2
从图1.2中可以看出,WaitAll会阻碍当前线程(主线程#10),等待所有异步的对象都执行完毕(耗时最长的异步),才释放当前的线程,WaitAll/WaitAny的重载版本和WaitOne一样.
3, WaitAny
和WaitAll 基本上是一样的.我们可以使用 WaitAny 来指定某个/某几个委托先等待,修改Code1.2红色部分,使用WaitAny.
Code1.3
//把salayAsyc异步的句柄保存到WaitHandle 对象中
WaitHandle[] handles = { salayAsyc.AsyncWaitHandle };
//阻碍当前线程,直到所有异步调用结束.
WaitHandle.WaitAny(handles);
![](http://img.e-com-net.com/image/product/3fda2657e0e2498a9b89d2a2dd706a38.png)
图1.3
我们阻碍了DoAntherJob(#10)线程,直到Salary异步调用计算完成.同样我们可以巧用这三个方法来改变我们方法执行的顺序.
释放资源
Code2
1
static
void
OnSalaryCallback(IAsyncResult asyncResult)
2
![](http://img.e-com-net.com/image/product/8bf85857a9e14d23a651e7c8ef856bcc.gif)
{
3
//通过AsyncDelegate 获取原始的委托对象
4
AsyncResult obj = (AsyncResult)asyncResult;
5
MyThirdAsyncCode.AsyncTest.SalaryEventHandler del =
(MyThirdAsyncCode.AsyncTest.SalaryEventHandler)obj.AsyncDelegate;
6![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
7
decimal val = del.EndInvoke(asyncResult);
8
asyncResult.AsyncWaitHandle.Close();//显示的释放资源
9
}
当开始调用BeginXXX后,就会创建一个新的AsyncResult对象.这个对象会构造一个WaitHandle句柄(通过AsyncWaitHandle访问),当我们EndXXX后,并不会马上关闭这个句柄,而是等待垃圾收集器来关闭,这时候我们最后在调用EndXXX完成后,显示的关闭这个句柄.
说到这里,我们基本上把异步方法都解释一遍,下面我们来看看重构的异步对象,我们也可以细细体会异步对象的内部执行代码..下面Code3.1/3.2/3.3代码来自Jeffery Richard大师的Power Threading类库,具体可查看http://msdn.microsoft.com/en-us/magazine/cc163467.aspx
1步,构造一个内部无参的AsyncResultNoResult对象,继承IAsyncResult接口(保留原创的注释)
Code3.1
1
internal
class
AsyncResultNoResult : IAsyncResult
2
![](http://img.e-com-net.com/image/product/8bf85857a9e14d23a651e7c8ef856bcc.gif)
{
3
// Fields set at construction which never change while
4
// operation is pending
5
private readonly AsyncCallback m_AsyncCallback;
6
private readonly Object m_AsyncState;
7![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
8
// Fields set at construction which do change after
9
// operation completes
10
private const Int32 c_StatePending = 0;
11
private const Int32 c_StateCompletedSynchronously = 1;
12
private const Int32 c_StateCompletedAsynchronously = 2;
13
private Int32 m_CompletedState = c_StatePending;
14![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
15
// Field that may or may not get set depending on usage
16
private ManualResetEvent m_AsyncWaitHandle;
17![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
18
// Fields set when operation completes
19
private Exception m_exception;
20![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
21
public AsyncResultNoResult(AsyncCallback asyncCallback, Object state)
22![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
23
m_AsyncCallback = asyncCallback;
24
m_AsyncState = state;
25
}
26![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
27
public void SetAsCompleted(
28
Exception exception, Boolean completedSynchronously)
29![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
30
// Passing null for exception means no error occurred.
31
// This is the common case
32
m_exception = exception;
33![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
34
// The m_CompletedState field MUST be set prior calling the callback
35
Int32 prevState = Interlocked.Exchange(ref m_CompletedState,
36
completedSynchronously ? c_StateCompletedSynchronously :
37
c_StateCompletedAsynchronously);
38
if (prevState != c_StatePending)
39
throw new InvalidOperationException(
40
"You can set a result only once");
41![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
42
// If the event exists, set it
43
if (m_AsyncWaitHandle != null) m_AsyncWaitHandle.Set();
44![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
45
// If a callback method was set, call it
46
if (m_AsyncCallback != null) m_AsyncCallback(this);
47
}
48![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
49
public void EndInvoke()
50![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
51
// This method assumes that only 1 thread calls EndInvoke
52
// for this object
53
if (!IsCompleted)
54![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
55
// If the operation isn't done, wait for it
56
AsyncWaitHandle.WaitOne();
57
AsyncWaitHandle.Close();
58
m_AsyncWaitHandle = null; // Allow early GC
59
}
60![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
61
// Operation is done: if an exception occured, throw it
62
if (m_exception != null) throw m_exception;
63
}
64![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
65![](http://img.e-com-net.com/image/product/561925b32f8f4c9d9561af4d649930ae.gif)
Implementation of IAsyncResult#region Implementation of IAsyncResult
66![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
public Object AsyncState
{ get
{ return m_AsyncState; } }
67![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
68
public Boolean CompletedSynchronously
69![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
70
get
71![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
72
return Thread.VolatileRead(ref m_CompletedState) ==
73
c_StateCompletedSynchronously;
74
}
75
}
76![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
77
public WaitHandle AsyncWaitHandle
78![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
79
get
80![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
81
if (m_AsyncWaitHandle == null)
82![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
83
Boolean done = IsCompleted;
84
ManualResetEvent mre = new ManualResetEvent(done);
85
if (Interlocked.CompareExchange(ref m_AsyncWaitHandle,
86
mre, null) != null)
87![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
88
// Another thread created this object's event; dispose
89
// the event we just created
90
mre.Close();
91
}
92
else
93![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
94
if (!done && IsCompleted)
95![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
96
// If the operation wasn't done when we created
97
// the event but now it is done, set the event
98
m_AsyncWaitHandle.Set();
99
}
100
}
101
}
102
return m_AsyncWaitHandle;
103
}
104
}
105![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
106
public Boolean IsCompleted
107![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
108
get
109![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
110
return Thread.VolatileRead(ref m_CompletedState) !=
111
c_StatePending;
112
}
113
}
114
#endregion
115
}
2步,继承AsyncResultNoResult对象,并且为他提供返回值和泛型的访问
Code3.2
1
internal
class
AsyncResult
<
TResult
>
: AsyncResultNoResult
2
![](http://img.e-com-net.com/image/product/8bf85857a9e14d23a651e7c8ef856bcc.gif)
{
3
// Field set when operation completes
4
private TResult m_result = default(TResult);
5![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
6
public AsyncResult(AsyncCallback asyncCallback, Object state) :
7![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
base(asyncCallback, state)
{ }
8![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
9
public void SetAsCompleted(TResult result,
10
Boolean completedSynchronously)
11![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
12
// Save the asynchronous operation's result
13
m_result = result;
14![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
15
// Tell the base class that the operation completed
16
// sucessfully (no exception)
17
base.SetAsCompleted(null, completedSynchronously);
18
}
19![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
20
new public TResult EndInvoke()
21![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
22
base.EndInvoke(); // Wait until operation has completed
23
return m_result; // Return the result (if above didn't throw)
24
}
25
}
3步,模拟长时间的异步工作
Code3.3
1
internal
sealed
class
LongTask
2
![](http://img.e-com-net.com/image/product/8bf85857a9e14d23a651e7c8ef856bcc.gif)
{
3
private Int32 m_ms; // Milliseconds;
4![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
5
public LongTask(Int32 seconds)
6![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
7
m_ms = seconds * 1000;
8
}
9![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
10
// Synchronous version of time-consuming method
11
public DateTime DoTask()
12![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
13
Thread.Sleep(m_ms); // Simulate time-consuming task
14
return DateTime.Now; // Indicate when task completed
15
}
16![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
17
// Asynchronous version of time-consuming method (Begin part)
18
public IAsyncResult BeginDoTask(AsyncCallback callback, Object state)
19![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
20
// Create IAsyncResult object identifying the
21
// asynchronous operation
22
AsyncResult<DateTime> ar = new AsyncResult<DateTime>(
23
callback, state);
24![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
25
// Use a thread pool thread to perform the operation
26
ThreadPool.QueueUserWorkItem(DoTaskHelper, ar);
27![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
28
return ar; // Return the IAsyncResult to the caller
29
}
30![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
31
// Asynchronous version of time-consuming method (End part)
32
public DateTime EndDoTask(IAsyncResult asyncResult)
33![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
34
// We know that the IAsyncResult is really an
35
// AsyncResult<DateTime> object
36
AsyncResult<DateTime> ar = (AsyncResult<DateTime>)asyncResult;
37![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
38
// Wait for operation to complete, then return result or
39
// throw exception
40
return ar.EndInvoke();
41
}
42![](http://img.e-com-net.com/image/product/b5ccfbfdc70d443ba19cbdc6a5005b86.gif)
43
// Asynchronous version of time-consuming method (private part
44
// to set completion result/exception)
45
private void DoTaskHelper(Object asyncResult)
46![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
47
// We know that it's really an AsyncResult<DateTime> object
48
AsyncResult<DateTime> ar = (AsyncResult<DateTime>)asyncResult;
49
try
50![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
51
// Perform the operation; if sucessful set the result
52
DateTime dt = DoTask();
53
ar.SetAsCompleted(dt, false);
54
}
55
catch (Exception e)
56![](http://img.e-com-net.com/image/product/437570a32a8e47669b1b8f34e2a85bac.gif)
{
57
// If operation fails, set the exception
58
ar.SetAsCompleted(e, false);
59
}
60
}
61
}
来自Jeffrey Richter大师更多更详细的异步操作方法, 请查看http://www.wintellect.com/PowerThreading.aspx,对于一些朋友可能看不懂Code3.1-3.3代码(其实没什么所谓的),因为涉及到过多的线程知识,这里出于让你获得更多的更深层次的(异步)认识为目的,才提供上面代码.