zoukankan      html  css  js  c++  java
  • 多线程之异步编程模式

    .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
  • 相关阅读:
    【转】Android实战技巧:ViewStub的应用
    3.11 返回数据到前一个Activity
    在用android日志的时候老是弹出一个窗口,内容为:"Copy" did not complete normally. Please see the log 和 什么函数,能达到和android手机上按“返回”键一样的效果?
    Windows下的Android模拟器设置内存大小
    AlertDialog.Builder对话框类的用法(二)
    android版计算器
    【转】Android中字符串的拆分split
    readelf
    6200 uboot 测试版分析(二)
    cpp
  • 原文地址:https://www.cnblogs.com/mandel/p/3510913.html
Copyright © 2011-2022 走看看