Windows Store apps开发[36]Await和Async

注:本文由BeyondVincent(破船)原创首发

        转载请注明出处:BeyondVincent(破船)@DevDiv.com



更多内容请查看下面的帖子


[DevDiv原创]Windows 8 开发Step by Step


    注1:本文译自Programming Windows, 6th Edition Charpter 7 Await and Async

    注2:本文内容是关于Await和Async的一个简介,关于详细内容,我会在后续文章中进行介绍

    注3:通过本文的阅读,你可以知道如何在Windows 8中进行简单的异步调用,以及一些注意事项。


    C# 5.0的关键字await允许我们对异步的操作就如同正常方法的调用一样。SimplePad2程序除了在应用程序栏中的按钮处理打开和保存外,跟SimplePad1一样。下面是Save按钮的Click事件处理代码:

工程:SimplePad2 | 文件:MainPage.xaml.cs(节选)

async void OnSaveAsAppBarButtonClick(object sender, RoutedEventArgs args)
{
    FileSavePicker picker = new FileSavePicker();
    picker.DefaultFileExtension = ".txt";
    picker.FileTypeChoices.Add("Text", new List<string> { ".txt" });

    // Asynchronous call!
    StorageFile storageFile = await picker.PickSaveFileAsync();

    if (storageFile == null)
        return;

    // Asynchronous call!
    await FileIO.WriteTextAsync(storageFile, txtbox.Text);
}
    注意两个await前面的注释。PickSaveFileAsync实际上是返回一个IAsyncOperation,一般你需要给它设置一个完成处理的函数,然后在这个完成处理回调中调用GetResults以获取StorageFile对象。await操作看似绕过了所有复杂的东西,而是直接简单的返回 StorageFile。这究竟是怎么回事呢?

    这看起来很神奇,但是许多杂乱的实现细节已经隐藏起来了。C#编译器生成回调(callback),并且调用GetResults。但是await操作同样将该方法转入一个状态机。(But what the await operator also does is turn the method in which it’s used into a state machine.)OnSaveAsAppBarButtonClick方法开始执行很正常,直到PickSaveFileAsync被调用以及await第一次出现。

    虽然名为await,但是await并不等待操作完成。相反,Click处理函数在这里退出了。控制权回到Windows。其它的代码,可以在程序用户界面线程继续执行,同时也可以对进行文件选取(file-picker)。当文件选取器消失了,即用户对文件选取的结果已经出来了,那么UI线程就准备执行一些代码——继续执行Click处理函数:赋值storageFile变量,然后继续往下执行,直到下一个await操作。就像这样,可以一直往下执行许多await操作(如果有),直到函数完成。

    在Click处理函数中的最后一行代码调用了静态方法FileIO.WriteTextAsync。严格来将,这里的await操作符可以不需要,因为在这里并不需要这个方法的执行结果。File.WriteTextAsync方法不返回任何内容,并且在Click处理函数中,并没有其它代码依赖于此的。因此在这种ing狂下,await操作符可以移除,程序代码如下:

FileIO.WriteTextAsync(storageFile, txtbox.Text);

    你会收到一条来自编译器的警告消息,但是这没问题。await操作符只在下面两种情况比较关键:你需要从异步方法中获得一个返回值,再者就是在程序逻辑上继续执行之前,异步方法必须完成则需要使用await操作符。
    下面是Open按钮的Click事件处理函数,使用了静态方法FileIO.ReadTextAsync:

工程:SimplePad2 | 文件:MainPage.xaml.cs(节选)

async void OnOpenAppBarButtonClick(object sender, RoutedEventArgs args)
{
    FileOpenPicker picker = new FileOpenPicker();
    picker.FileTypeFilter.Add(".txt");

    // Asynchronous call!
    StorageFile storageFile = await picker.PickSingleFileAsync();

    if (storageFile == null)
        return;

    // Asynchronous call!
    txtbox.Text = await FileIO.ReadTextAsync(storageFile);
}


    在await出现之前,C#中异步操作的调用总是有悖于语言的必要组织结构。await操作符带来了必要组织结构,并将异步调用转换为一系列普通方法的调用。而且在Click处理函数中的所有事情都是在UI线程中进行的,因此必用考虑用户界面对象的访问。虽然await的使用,更加简单,但是你要记住的是如果一个函数中出现了await,那么实际上在后端是将该函数分片处理的。

    这里有一些await的使用条款。await不能出现在异常处理的catch或finally语句中。而它可以出现在try语句中,这也是捕获异步函数发生错误的方法。同关键字,样还提供了取消操作,以及一些异步函数的进度通知。这些具体细节我将在后面的异步操作章节中介绍。

    如果函数中出现了await操作符,那么该函数必须用async标识,但是async并不做其它更多的事情。在早期的C#版本中,await并不是一个关键字,所以程序员可以将这个单词(await)用作变量名或属性名,或者其它任何内容。C#5.0中添加了await关键字将改变这一现状,不过使用async标识来限制函数中的await。async不会改变函数的签名——上面的方法任然是Click的处理方法。但是async(以及await)不能被用在入口点,如Main或者类的构造函数中

    如果你需要在初始化一个FrameworkElement子类时调用异步方法,那么请在Loaded事件处理函数中进行,并将处理函数标记为async:

public MainPage()
{
    this.InitializeComponent();
    ...
    Loaded += OnLoaded;
}
async void OnLoaded(object sender, RoutedEventArgs arg)
{
    ...
}

或者,如果你喜欢的话,可以按照下面的代码,将Loaded处理函数定义为一个异步函数:

public MainPage()
{
    this.InitializeComponent();

    ...

    Loaded += async (sender, args) =>
    {
        ...
    };
}

看到参数列表前的async了吗?

    


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值