读书人

【Windows8开发】异步编程进阶篇之 Pl

发布时间: 2012-09-25 09:55:59 作者: rapoo

【Windows8开发】异步编程进阶篇之 Platform::Exception及task间的异常控制
先考虑下使用传统Thread API时,线程间的异常控制往往是一件相当痛苦的事情,由于某个线程的异常未捕获导致整个程序crash的情况也许很多人都碰到过。比如如果有一组任务链处理序列,我们往往需要对每个线程都详细考虑其可能抛出的各种异常,如果需要把一个异常从一个线程抛到另外一个线程进行处理时,那更需要多费很多周折,而且往往费时费力最后却还总是会发现这样那样的疏忽与漏洞。那WinRT提供的task有何不同呢?
在给出答案之前,先介绍下Metro程序中如何使用WinRT中定义Exception。WinRT中所有的异常都继承于Platform::Exception,比如ClassNotRegisteredException,FailureException,COMException等等。例如要抛出一个Failure的异常:

create_task([] {       throw ref new Platform::Exception(E_FAIL);}).then([]  (){       throw ref new Platform::Exception(E_FAIL);}).then([]  (task<void> t){       try {              t.get();       } catch (Platform::Exception^ e) {              // handle the exception       }});

执行结果是这样的,初始任务中E_FAIL异常被抛出,第一个then中的任务处理未被执行,第二个then中的任务捕获了开始抛出的E_FAIL异常。简单解释一下,当开始的task抛出异常时,由于第一个then中的处理是value-based,所以不再会被执行,而第二个then是task-based的(参数为task<void>),所以仍旧会被调用,其中t.get()处理的一个作用是可以获得之前task的返回值,虽然本例中并无返回值,但get还有个作用是可以抛出前期任务中发生的所有异常。也就是说,我们可以在task的最后增加一个延续任务(Continuation),在此任务中通过get方法抛出所有前期task发生的异常,并在此处统一catch处理。这可以让我们很方便地控制前后task中发生的所有异常。当然,正常的处理并不是去捕获所有发生的异常( 不论是预期内还是预期外)来保证程序不会crash,而是应该去处理在该处应该处理的异常,而忽略一些期望外的异常,让这些异常继续被抛出,即使导致程序crash,也不至于埋藏掉一些本该很容易被发现的错误。到此,不知大家是否也有相同的感触,task的这种异常处理的方式,可以帮助开发者很方便的解决一些使用传统thread API很难解决的异常控制问题。

读书人网 >编程

热点推荐