兼职网站排行,怎么做业务推广技巧,华夏润达建设有限公司网站,旅游类网站设计本文内容
任务和异步编程模型 (APM)任务和基于事件的异步模式 (EAP)任务和等待句柄
.NET 中异步模式的简短历史记录#xff1a;
.NET Framework 1.0 引进了 IAsyncResult 模式#xff0c;也称为异步编程模型 (APM) 或 Begin/End 模式。.NET Framework 2.0 增加了基于事件的…本文内容
任务和异步编程模型 (APM)任务和基于事件的异步模式 (EAP)任务和等待句柄
.NET 中异步模式的简短历史记录
.NET Framework 1.0 引进了 IAsyncResult 模式也称为异步编程模型 (APM) 或 Begin/End 模式。.NET Framework 2.0 增加了基于事件的异步模式 (EAP)。.NET Framework 4 引进了基于任务的异步模式 (TAP)它取代了 APM 和 EAP并能够轻松构建从早期模式中迁移的例程。
1、任务和异步编程模型 (APM)
1.1 从 APM 到 TAP
因为异步编程模型 (APM) 模式的结构合理而且能够轻松生成包装将 APM 实现公开为 TAP 实现。 .NET Framework 4 及更高版本包含采用 FromAsync 方法重载形式的帮助器例程来实现这种转换。
请考虑 Stream 类及其 BeginRead 和 EndRead 方法它们代表与同步 Read 方法对应的 APM
public int Read(byte[] buffer, int offset, int count)public IAsyncResult BeginRead(byte[] buffer, int offset,int count, AsyncCallback callback,object state)public int EndRead(IAsyncResult asyncResult)可以使用 TaskFactoryTResult.FromAsync 方法来实现此操作的 TAP 包装如下所示
public static Taskint ReadAsync(this Stream stream,byte[] buffer, int offset,int count)
{if (stream null)throw new ArgumentNullException(stream);return Taskint.Factory.FromAsync(stream.BeginRead,stream.EndRead, buffer,offset, count, null);
}此实现类似于以下内容 public static Taskint ReadAsync(this Stream stream,byte [] buffer, int offset,int count){if (stream null)throw new ArgumentNullException(stream);var tcs new TaskCompletionSourceint();stream.BeginRead(buffer, offset, count, iar {try {tcs.TrySetResult(stream.EndRead(iar));}catch(OperationCanceledException) {tcs.TrySetCanceled();}catch(Exception exc) {tcs.TrySetException(exc);}}, null);return tcs.Task;
}1.2 从 TAP 到 APM
如果现有的基础结构需要 APM 模式则还需要采用 TAP 实现并在需要 APM 实现的地方使用它。 由于任务可以组合并且 Task 类实现 IAsyncResult你可以使用一个简单的 helper 函数执行此操作。 以下代码使用 TaskTResult 类的扩展但可以对非泛型任务使用几乎相同的函数。
public static IAsyncResult AsApmT(this TaskT task,AsyncCallback callback,object state)
{if (task null)throw new ArgumentNullException(task);var tcs new TaskCompletionSourceT(state);task.ContinueWith(t {if (t.IsFaulted)tcs.TrySetException(t.Exception.InnerExceptions);else if (t.IsCanceled)tcs.TrySetCanceled();elsetcs.TrySetResult(t.Result);if (callback ! null)callback(tcs.Task);}, TaskScheduler.Default);return tcs.Task;
}现在请考虑具有以下 TAP 实现的用例
public static TaskString DownloadStringAsync(Uri url)并且想要提供此 APM 实现
public IAsyncResult BeginDownloadString(Uri url,AsyncCallback callback,object state)public string EndDownloadString(IAsyncResult asyncResult)以下示例演示了一种向 APM 迁移的方法
public IAsyncResult BeginDownloadString(Uri url,AsyncCallback callback,object state)
{return DownloadStringAsync(url).AsApm(callback, state);
}public string EndDownloadString(IAsyncResult asyncResult)
{return ((Taskstring)asyncResult).Result;
}2、任务和等待句柄
2.1 从等待句柄到 TAP
虽然等待句柄不能实现异步模式但高级开发人员可以在设置等待句柄时使用 WaitHandle 类和 ThreadPool.RegisterWaitForSingleObject 方法实现异步通知。 可以包装 RegisterWaitForSingleObject 方法以在等待句柄中启用针对任何同步等待的基于任务的替代方法
public static Task WaitOneAsync(this WaitHandle waitHandle)
{if (waitHandle null)throw new ArgumentNullException(waitHandle);var tcs new TaskCompletionSourcebool();var rwh ThreadPool.RegisterWaitForSingleObject(waitHandle,delegate { tcs.TrySetResult(true); }, null, -1, true);var t tcs.Task;t.ContinueWith( (antecedent) rwh.Unregister(null));return t;
}使用此方法可以在异步方法中使用现有 WaitHandle 实现。 例如若要限制在任何特定时间执行的异步操作数可以利用信号灯System.Threading.SemaphoreSlim 对象。 可以将并发运行的操作数目限制到 N方法为初始化到 N 的信号量的数目、在想要执行操作时等待信号量并在完成操作时释放信号量
static int N 3;static SemaphoreSlim m_throttle new SemaphoreSlim(N, N);static async Task DoOperation()
{await m_throttle.WaitAsync();// do workm_throttle.Release();
}还可以构建不依赖等待句柄就完全可以处理任务的异步信号量。 若要执行此操作可以使用 使用基于任务的异步模式 中所述的用于在 Task。
2.2 从 TAP 到等待句柄
正如前面所述 Task 类实现 IAsyncResult且该实现公开 IAsyncResult.AsyncWaitHandle 属性该属性会返回在 Task 完成时设置的等待句柄。 可以获得 WaitHandle 的 Task 如下所示
WaitHandle wh ((IAsyncResult)task).AsyncWaitHandle;