多线程之异步编程模式

.Net为执行异步操作提供了三中模式:

  • 异步编程模型 (APM)
  • 基于事件的异步模式(EAP)
  • 基于任务的异步模式(TAP)

1.异步编程模型(APM)。

使用IAsyncResult设计模式的异步操作通过Begin操作和End操作两个方法实现。

在调用Begin操作后,调用线程继续执行指令,同时异步操作在另外一个线程上执行,调用线程调用End方法来获取结果。

Code:

 1 namespace Examples
 2 {
 3     public class Progrom
 4     {
 5         public static void Main()
 6         {
 7             AsyncWorkTest work = new AsyncWorkTest();
 8             IAsyncResult result = work.BeginWork(CallBack, null);
 9             Console.WriteLine("Work is begining...");
10             string ret = work.EndWork(result);
11             Console.WriteLine(ret);
12             Console.WriteLine("Work is end...");
13             Console.ReadKey();
14         }
15 
16         static void CallBack(object obj)
17         {
18             //do someing
19         }
20     }
21 
22     public class AsyncResult : IAsyncResult
23     {
24         public AsyncResult()
25         {
26             //Accept parameters
27         }
28         private object asyncState;
29         private volatile bool isCompleted;
30         private volatile bool completedSynchronously;
31         private ManualResetEvent asynWaitHandle;
32 
33         public string Result = "Mandel";
34 
35         public object AsyncState
36         {
37             get { return asyncState; }
38         }
39         public WaitHandle AsyncWaitHandle
40         {
41             get
42             {
43                 if (this.asynWaitHandle == null)
44                 {
45                     Interlocked.CompareExchange<ManualResetEvent>(ref this.asynWaitHandle, new ManualResetEvent(false), null);
46                 }
47                 return asynWaitHandle;
48             }
49         }
50         public bool CompletedSynchronously
51         {
52             get { return completedSynchronously; }
53         }
54         public bool IsCompleted
55         {
56             get { return isCompleted; }
57         }
58 
59         public void Work()
60         {
61             //do someing
62             Thread.Sleep(3000); ;
63             Result = "The Silent Southern Girl";
64             asyncState = this;
65             completedSynchronously = false;
66             isCompleted = true;
67             asynWaitHandle.Set();
68         }
69 
70     }
71 
72     public class AsyncWorkTest
73     {
74         public IAsyncResult BeginWork(AsyncCallback callback, object state)
75         {
76             AsyncResult result = new AsyncResult();
77             ThreadPool.QueueUserWorkItem((action) =>
78             {
79                 result.Work();
80                 if (callback != null)
81                 {
82                     callback((AsyncResult)state);
83                 }
84             }, state);
85             return result;
86         }
87 
88         public string EndWork(IAsyncResult re)
89         {
90             AsyncResult result = (AsyncResult)re;
91             result.AsyncWaitHandle.WaitOne();
92             return result.Result;
93         }
94     }
95 
96 }
View Code

如果等待异步操作结果时需要阻塞调用线程,可以使用以下方法:

  •   使用AsyncWaitHandle阻止调用线程
  •   调用结束异步操作来阻止调用线程(本例子即使用这个)
  •   轮询异步操作状态来阻止调用线程。

如果等待异步操作结果时不能阻塞调用线程,可使用以下方法:

  • 使用AsyncCallback委托,在委托中结束异步操作。

2.基于事件的异步编程模式(EAP)

 基于事件的异步操作模式具有多线程应用程序的优点,同时隐匿了多线程设计中固有的许多问题。使用EAP类讲能够:

  • 在后台执行耗时任务,不会中断应用程序
  • 可同时执行多个操作,每个操作完成讲会接到通知
  • 等待资源变得可用,但不会停止("挂起")您的应用程序
  • 使用事件和委托模型与挂起的异步操作进行通信

 BackgroundWorker组件是典型的封装好的EAP。

 支持基于事件的异步编程模型的类将会提供若干个异步执行方法MethodNameAsync,支持取消异步的方法MethodNameCancelAsync,可以提供进度报告的事件onProgressChanged. 支持异步完成后通知事件onWorkCompleted。

Code:

  1  class EAPTest
  2     {
  3         public static void Main()
  4         {
  5             Work myWork = new Work();
  6             myWork.onProgressChanged += new ProgressChangedEventHandler(myWork_onProgressChanged);
  7             myWork.onWorkCompleted += new WorkCompletedEventHandler(myWork_onWorkCompleted);
  8             myWork.WoekAsync("Mandel");
  9             myWork.WoekAsync("Alan");
 10             Thread.Sleep(4000);
 11             myWork.CancelAsync("Alan");
 12             Console.ReadKey();
 13         }
 14 
 15         static void myWork_onProgressChanged(WorkProgressChangedEventArgs e)
 16         {
 17             Console.WriteLine("Worked" + e.TaskID + " " + e.ProgressPercentage.ToString() + "% --------------");
 18         }
 19 
 20         static void myWork_onWorkCompleted(object sender, WorkCompletedEventArgs e)
 21         {
 22             Console.WriteLine("Work " + e.TaskID + "Completed---------");
 23         }
 24     }
 25 
 26     //delegate
 27     public delegate void ProgressChangedEventHandler(WorkProgressChangedEventArgs e);
 28     public delegate void WorkCompletedEventHandler(object sender, WorkCompletedEventArgs e);
 29     class Work
 30     {
 31         private delegate void WorkerEventHandler(AsyncOperation asyncOp, object taskID);
 32         private delegate void www();
 33         private SendOrPostCallback onProgressReportDelegate;
 34         private SendOrPostCallback onCompletedDelegate;
 35 
 36         public event ProgressChangedEventHandler onProgressChanged;
 37         public event WorkCompletedEventHandler onWorkCompleted;
 38 
 39         private HybridDictionary userStateToLifetime = new HybridDictionary();
 40 
 41         public Work()
 42         {
 43             onProgressReportDelegate = new SendOrPostCallback(ReportProgress);
 44             onCompletedDelegate = new SendOrPostCallback(WorkCompleted);
 45         }
 46         private void WorkCompleted(object operationState)
 47         {
 48             WorkCompletedEventArgs e = operationState as WorkCompletedEventArgs;
 49             if (onWorkCompleted != null)
 50             {
 51                 onWorkCompleted(this, e);
 52             }
 53         }
 54         private void ReportProgress(object state)
 55         {
 56             WorkProgressChangedEventArgs e = state as WorkProgressChangedEventArgs;
 57             if (onProgressChanged != null)
 58             {
 59                 onProgressChanged(e);
 60             }
 61         }
 62 
 63         public virtual void WoekAsync(string taskId)
 64         {
 65             // Create an AsyncOperation for taskId.
 66             AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(taskId);
 67             lock (userStateToLifetime.SyncRoot)
 68             {
 69                 if (userStateToLifetime.Contains(taskId))
 70                 {
 71                     throw new ArgumentException("Task ID parameter must be unique", "taskId");
 72                 }
 73 
 74                 userStateToLifetime[taskId] = asyncOp;
 75             }
 76             // Start the asynchronous operation.
 77             WorkerEventHandler workerDelegate = new WorkerEventHandler(Worker);
 78             workerDelegate.BeginInvoke(asyncOp, taskId, null, null);
 79         }
 80         private void Worker(AsyncOperation asyncOp, object taskID)
 81         {
 82             Exception e = null;
 83             ProgressChangedEventArgs progressEventArg;
 84             for (int i = 0; i < 5; i++)
 85             {
 86                 Thread.Sleep(1000);
 87                 Console.WriteLine(i);
 88             }
 89             if (!TaskCanceled(asyncOp.UserSuppliedState))
 90             {
 91                 //Do the work
 92                 try
 93                 {
 94                     Console.WriteLine("Come On! " + taskID);
 95                     Console.WriteLine("Work " + taskID.ToString() + " is working");
 96                     progressEventArg = new WorkProgressChangedEventArgs(taskID, 50, new object());
 97                     asyncOp.Post(this.onProgressReportDelegate, progressEventArg);
 98                     Console.WriteLine("Work " + taskID.ToString() + " has been completed");
 99                     progressEventArg = new WorkProgressChangedEventArgs(taskID, 100, new object());
100                     asyncOp.Post(this.onProgressReportDelegate, progressEventArg);
101                 }
102                 catch (Exception ex)
103                 {
104                     e = ex;
105                 }
106                 this.CompletionMethod(taskID, e, TaskCanceled(asyncOp.UserSuppliedState), asyncOp);
107             }
108             else
109             {
110                 Console.WriteLine("Work " + taskID.ToString() + " has been canceled");
111             }
112         }
113 
114         public void CancelAsync(object taskId)
115         {
116             AsyncOperation asyncOp = userStateToLifetime[taskId] as AsyncOperation;
117             if (asyncOp != null)
118             {
119                 lock (userStateToLifetime.SyncRoot)
120                 {
121                     userStateToLifetime.Remove(taskId);
122                 }
123             }
124         }
125 
126         private bool TaskCanceled(object taskId)
127         {
128             return (userStateToLifetime[taskId] == null);
129         }
130 
131         private void CompletionMethod(object taskID, Exception exception, bool canceled, AsyncOperation asyncOp)
132         {
133             if (!canceled)
134             {
135                 lock (userStateToLifetime.SyncRoot)
136                 {
137                     userStateToLifetime.Remove(asyncOp.UserSuppliedState);
138                 }
139             }
140             WorkCompletedEventArgs e = new WorkCompletedEventArgs(taskID.ToString(), exception, canceled, asyncOp.UserSuppliedState);
141             asyncOp.PostOperationCompleted(onCompletedDelegate, e);
142         }
143     }
144 
145     //Args
146     public class WorkProgressChangedEventArgs : ProgressChangedEventArgs
147     {
148         private object taskID = null;
149 
150         public WorkProgressChangedEventArgs(object value, int progressPercentage, object userToken)
151             : base(progressPercentage, userToken)
152         {
153             this.taskID = value;
154         }
155         /// <summary>
156         /// 任务标识
157         /// </summary>
158         public object TaskID
159         {
160             get
161             {
162                 return taskID;
163             }
164         }
165     }
166     public class WorkCompletedEventArgs : AsyncCompletedEventArgs
167     {
168         object taskID = "";
169         public WorkCompletedEventArgs(object value, Exception e, bool canceled, object state)
170             : base(e, canceled, state)
171         {
172             this.taskID = value;
173         }
174         /// <summary>
175         /// 任务标识
176         /// </summary>
177         public object TaskID
178         {
179             get
180             {
181                 RaiseExceptionIfNecessary();
182                 return taskID;
183             }
184         }
185     }
View Code

 

 

 

posted on 2014-01-13 23:39  象山  阅读(940)  评论(0编辑  收藏  举报

导航