当前位置: 首页 > news >正文

WinRT 异步模型

     开篇第一句:.net4.5中异步方法的实现远不如看起来的那么简单,编译器背后代替开发人员生成了大量的代码 做了好多事情使它看起来简单了,这些代码和过去实现异步操作时必须开发人员手动编写并维护的样板代码的数量类似。此外,编译器生成的代码会在 .NET Framework 中调用库代码,再次代替开发人员完成更多的工作。要获得正确的思维模式并使用这一模式做出合适的开发决策,重要的一点是了解编译器代替您生成了哪些内容。

     .net4.5中定义了大量的异步方法***Async(例如Windows.System.Launcher.LaunchUriAsync() )这些方法的返回类型是IAsyncInfo或者继承自该接口的IAsyncAction、IAsyncActionWithProgress、IAsyncOperation 和 IAsyncOperationWithProgress等(注意在Windows 8 Consumer Preview版本中这些方法都改为热启动的,异步方法会在将操作返回到调用程序之前启动操作,所以无需***Async.Start()等操作)。

WinRT 异步模型的核心接口依托于 IAsyncInfo 而构建。该核心接口可以定义异步操作(例如,当前状态、取消操作的功能和失败操作的错误等)的属性。用户可以通过该类型的返回值得到异步方法***Async的当前状态Status,标识Id,以及该异步方法失败的错误信息ErrorCode,并且可以取消和关闭该操作。

View Code
    public interface IAsyncInfo
    {
        // 摘要:
        //     Gets a string that describes an error condition of the asynchronous operation.
        //
        // 返回结果:
        //     The error string.
        Exception ErrorCode { get; }
        //
        // 摘要:
        //     Gets the handle of the asynchronous operation.
        //
        // 返回结果:
        //     The handle.
        uint Id { get; }
        //
        // 摘要:
        //     Gets a value that indicates the status of the asynchronous operation.
        //
        // 返回结果:
        //     The status of the operation.
        AsyncStatus Status { get; }

        // 摘要:
        //     Cancels the asynchronous operation.
        void Cancel();
        //
        // 摘要:
        //     Closes the asynchronous operation.
        void Close();
    }

但该特定接口缺少对异步操作来说无疑是至关重要的功能:当操作完成时,通过回调通知监听器以及异步操作运行时进度报告。该功能有意地划分到了四个依赖 IAsyncInfo的其他接口中,而 WinRT 中的每个异步操作都需要实施以下四个接口之一。

public interface IAsyncAction : IAsyncInfo
{    
      AsyncActionCompletedHandler Completed { get; set; }       
      void GetResults();
}
public interface  IAsyncOperation<TResult> : IAsyncInfo
{
    AsyncOperationCompletedHandler<TResult> Completed { get; set; }
    TResult GetResults();
}
public interface IAsyncActionWithProgress<TProgress> : IAsyncInfo
{
    AsyncActionWithProgressCompletedHandler<TProgress> Completed { get; set; }    
AsyncActionProgressHandler<TProgress> Progress { get; set; } void GetResults(); } public interface IAsyncOperationWithProgress<TResult, TProgress> : IAsyncInfo { AsyncOperationWithProgressCompletedHandler<TResult, TProgress> Completed { get; set; }
AsyncOperationProgressHandler<TResult, TProgress> Progress { get; set; } TResult GetResults(); }

例如我们可以这么使用:(更多信息请参考http://blogs.msdn.com/b/windowsappdev_cn/archive/2012/03/26/windows.aspx)

private void btnDoWork_Click(object sender, RoutedEventArgs e)
{    int result = 0;
var op = ThreadPool.RunAsync(delegate { result = Compute(); })
op.Completed = delegate(IAsyncAction asyncAction, AsyncStatus asyncStatus)
{
Dispatcher.RunAsync(CoreDispatcherPriority.Normal, delegate
{
switch (asyncStatus)
{
case AsyncStatus.Completed:
btnDoWork.Content = result.ToString();
break;
case AsyncStatus.Error:
btnDoWork.Content = asyncAction.ErrorCode.Message;
break;
case AsyncStatus.Canceled:
btnDoWork.Content = "A task was canceled";
break;
}
});
};}

但为了处理一个异步调用,我们就需要编写大量代码,手动处理完成回调,手动封送回 UI 线程,明确检查完成状态等等。于是一个关键字await应运而生。有了await我们可以这么写:

private async void btnDoWork_Click(object sender, RoutedEventArgs e)
{
try
{
int result = 0;
await ThreadPool.RunAsync(delegate { result = Compute(); }); // 该异步操作中产生的异常会被传播到当前线程中并在当前线程中得到处理。
btnDoWork.Content = result.ToString();
}
catch (Exception exc) { btnDoWork.Content = exc.Message; }
}

 

注意async关键字,使用 async 关键字标记方法,会导致 C# 或 Visual Basic 编译器使用状态机重新编写该方法的实施。借助此状态机,编译器可以在该方法中插入多个中断点,以便该方法可以在不阻止线程的情况下,挂起和恢复其执行。这些中断点不会随意地插入。它们只会在您明确使用 await 关键字的位置插入. 详细信息请参考:http://blogs.msdn.com/b/windowsappdev_cn/archive/2012/04/30/winrt-await.aspx

总结一下:

async关键字的作用

    1.告诉编译器你想在该方法中使用await关键字(只可以在标有async关键字的方法或者lambda表达式中使用await关键字),如果标有async方法中没有await,编译器编译时会发出警告。而编译器碰到使用aysnc标记的方法会使用状态机重新编写该方法的实施。这样该方法在await关键字出现的地方可以在不阻止线程的情况下,挂起和恢复其执行。

    2.告诉编译器来自该操作的任何异常将得到传播或作为结果返回(通过 GetResult),如果该方法返回值是Task或者Task<TResult>,就意味着任何返回值或者该方法中未处理的异常都会存储到返回的Task中;对于一个返回值是Void的方法来说,这意味着 任何异常都会传播到调用者的上下文中. 也就是上边例子中所展示的。

await关键字的作用

           告诉编译器在标记async的方法中插入一个挂起/恢复执行的点。

Task Task〈TResult>和WinRT异步方法之间的互换

在构建 WinRT 库时,该库中所有全局公开的异步操作都会强类型化为返回这四个接口之一。与此相对,从 .NET 库公开的新异步操作遵循基于任务的异步模式 (TAP)。对于不返回结果的操作返回 Task,而对于返回结果的操作则返回 Task<TResult>TaskTask<TResult> 不会实施这些 WinRT 接口,公共语言运行时 (CLR) 也不会暗中掩饰它们的差异(对于某些类型会如此,例如 WinRT Windows.Foundation.Uri 类型和 BCL System.Uri类型)。而是我们需要明确地从一种模式转换到另一种。Task和Task<>也可以使用AsAsyncAction, AsAsyncOperation<>转化为IAsyncAction、IAsyncActionWithProgress、IAsyncOperation 和 IAsyncOperationWithProgress等接口方法,后台实现机制为适配器模式。

Task<int> t;

t.AsAsyncAction();

t.AsAsyncOperation<int>

另外这些异步方法还可以通过AsTask和AsTask<>等方法转化成为Task或者Task<>,后台使用扩展方法实现,类似于Linq的实现方式。

IAsyncOperationWithProcess<int, string> op;

op.AsTask<int, string>

 

详细了解请参考以下链接。

Reference:

http://blogs.msdn.com/b/windowsappdev_cn/archive/2012/03/26/windows.aspx  

http://blogs.msdn.com/b/windowsappdev_cn/archive/2012/04/30/winrt-await.aspx

http://blogs.msdn.com/b/windowsappdev_cn/archive/2012/06/22/net-winrt.aspx

http://blogs.msdn.com/b/pfxteam/archive/2012/04/12/10293335.aspx

http://www.microsoft.com/en-us/download/details.aspx?id=19957

http://msdn.microsoft.com/zh-CN/async

 

关于TAP

在对比了早期IAsyncResult模式也叫APM模式和基于事件的异步模式Event-based Asynchronous PatternEAP,基于任务的异步模式Task-based Asynchronous Pattern 有很大的优势。对比一下代码:

public class MyClass
{
    public int Read(byte [] buffer, int offset, int count);
}

 The APM counterpart to this method would expose the following two methods:
public class MyClass
{
    public IAsyncResult BeginRead(
        byte [] buffer, int offset, int count, 
        AsyncCallback callback, object state);
    public int EndRead(IAsyncResult asyncResult);
}

The EAP counterpart would expose the following set of types and members:
public class MyClass
{
    public void ReadAsync(byte [] buffer, int offset, int count);
    public event ReadCompletedEventHandler ReadCompleted;
}

public delegate void ReadCompletedEventHandler(
    object sender, ReadCompletedEventArgs eventArgs);

public class ReadCompletedEventArgs : AsyncCompletedEventArgs
{
    public int Result { get; }
}

The TAP counterpart would expose the following single method:
public class MyClass
{
    public Task<int> ReadAsync(byte [] buffer, int offset, int count);
}

 详细参考:http://www.microsoft.com/en-us/download/details.aspx?id=19957

另外推荐两个很好的post,关于.net4中引入的异步编程任务并行库(Task Parallel Library)以及CLR4中线程池的内部实现。

http://www.codeproject.com/Articles/152765/Task-Parallel-Library-1-of-n

http://www.danielmoth.com/Blog/New-And-Improved-CLR-4-Thread-Pool-Engine.aspx

转载于:https://www.cnblogs.com/salomon/archive/2012/06/27/2565862.html

相关文章:

  • Ubuntu 10.04下Netbeans使用OpenJDK造成中文显示不正常的解决方案
  • SDL源码阅读笔记(1) 基本模块
  • container_of宏
  • 黑马程序员——关于接口和抽象类
  • 一阶负反馈的补偿特性
  • Freemark List 倒序输出
  • 如何访问一个类的保护变量
  • 一个简单的管理Web站点文件的页面程序(修改版)
  • 一个简单的库存控制模型
  • S型增长实例
  • js 弹出DIV层和关闭DIV层
  • 阻尼摆运动的系统动力学VENSIM模拟仿真
  • C# 指针之美
  • 传染病模型系统动力学VENSIM模拟
  • C++ 随机数函数
  • (三)从jvm层面了解线程的启动和停止
  • Android优雅地处理按钮重复点击
  • gitlab-ci配置详解(一)
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • JAVA 学习IO流
  • js对象的深浅拷贝
  • Nodejs和JavaWeb协助开发
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • SQL 难点解决:记录的引用
  • tensorflow学习笔记3——MNIST应用篇
  • text-decoration与color属性
  • 笨办法学C 练习34:动态数组
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 码农张的Bug人生 - 见面之礼
  • 每天一个设计模式之命令模式
  • 驱动程序原理
  • 首页查询功能的一次实现过程
  • 写给高年级小学生看的《Bash 指南》
  • const的用法,特别是用在函数前面与后面的区别
  • 扩展资源服务器解决oauth2 性能瓶颈
  • ​Python 3 新特性:类型注解
  • ###51单片机学习(1)-----单片机烧录软件的使用,以及如何建立一个工程项目
  • ###C语言程序设计-----C语言学习(3)#
  • (16)Reactor的测试——响应式Spring的道法术器
  • (2022 CVPR) Unbiased Teacher v2
  • (delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)
  • (Demo分享)利用原生JavaScript-随机数-实现做一个烟花案例
  • (超详细)2-YOLOV5改进-添加SimAM注意力机制
  • (附源码)springboot 校园学生兼职系统 毕业设计 742122
  • (免费领源码)python#django#mysql公交线路查询系统85021- 计算机毕业设计项目选题推荐
  • .Net Core缓存组件(MemoryCache)源码解析
  • .Net MVC + EF搭建学生管理系统
  • .net网站发布-允许更新此预编译站点
  • .net用HTML开发怎么调试,如何使用ASP.NET MVC在调试中查看控制器生成的html?
  • .vollhavhelp-V-XXXXXXXX勒索病毒的最新威胁:如何恢复您的数据?
  • ::
  • @ 代码随想录算法训练营第8周(C语言)|Day53(动态规划)
  • @Transactional 竟也能解决分布式事务?
  • [AutoSar]BSW_Com02 PDU详解