您的位置:首页 > 移动开发

Windows Store apps开发[37]调用自己的异步函数

2012-10-02 11:55 465 查看









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

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







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

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

注1:本文译自Programming Windows, 6th Edition Charpter 7 Calling Your Own Async Methods



假设你用类似下面的这个方法进行隔离存贮中文件保存的逻辑:

async void SaveFile(string text) 
{ 
    FileSavePicker picker = new FileSavePicker();
    picker.DefaultFileExtension = ".txt"; 
    picker.FileTypeChoices.Add("Text", new List<string> { ".txt" }); 
    StorageFile storageFile = await picker.PickSaveFileAsync();

    if (storageFile == null)
        return; 
    await FileIO.WriteTextAsync(storageFile, txtbox.Text); 
}


这个方法必须标记为async,因为它有await关键字。然后你可以在OnSaveAsAppBarButtonClick函数中这样调用:

void OnSaveAsAppBarButtonClick(object sender, RoutedEventArgs args)
{
    SaveFile(txtbox.Text);
}


OnSaveAsAppBarButtonClick调用SaveFile发生什么呢:SaveFile开始执行,直到第一个await后的PickSaveFileAsync被调用,在这里,SaveFile函数终止并将控制权返回给OnSaveAsAppBarButtonClick函数。当PickSaveFileAsync结果准备好了,SaveFile剩余的代码继续被执行。

在这种特殊情况下,是正确的。然而,如果如果你想要OnSaveAsAppBarButtonClick方法等待SaveFile的执行,必须包含await关键字,并用async标识OnSaveAsAppBarButtonClick方法:

async void OnSaveAsAppBarButtonClick(object sender, RoutedEventArgs args)
{
    await SaveFile(txtbox.Text);
}


但是,当你这样做的话,SaveFile必须要改变一下。它不能再返回void。你可以有许多种方法修改SaveFile,但是可能最简单方法就是将返回类型修改为Task:

async Task SaveFile(string text) 
{ 
    ...
}


在这里,你可能想将方法的名字改为SaveFileAsync,标识这是一个异步方法,可以被等待。即使在SaveFileAsync方法中没有写明运行在别的线程里,但是调用SaveFileAsync的异步方法会在另外的线程中处理。

下面的OnOpenAppBarButtonClick与ReadFileAsync方法又有点不同。你可能希望ReadFileAsync方法返回文件中的文本内容,所以返回类型不是Task,而是Task<string>:

async Task<string> ReadFileAsync()
{
    FileOpenPicker picker = new FileOpenPicker();
    picker.FileTypeFilter.Add(".txt");
    StorageFile storageFile = await picker.PickSingleFileAsync();
    if (storageFile == null)
        return null;
    return await FileIO.ReadTextAsync(storageFile);
}


然后可以像如下调用ReadFileAsync:

async void OnOpenAppBarButtonClick(object sender, RoutedEventArgs args) 
{ 
    string text = await ReadFileAsync(); 
    if (text != null) 
        txtbox.Text = text; 
}


认识到这些所有的代码都在用户界面线程执行很重要。你不用担心UI对象的访问。FileIO的两个方法是在别的线程中运行的,由于ReadFileAsync方法调用了其它的异步方法,所以它也是异步的。方法中的其它代码则在UI线程运行。

如果你自己写的代码需要很长的处理时间,而你不希望在UI线程中处理,替代传统的技术(创建并执行线程)是考虑使用与Windows Runtime一样的基于任务的方法。你可以将要执行的代码以函数的方式传递给静态方法Task.Run。如下示例:

Task<double> BigJobAsync(int arg1, int arg2) 
{
    return Task.Run<double>(() => 
    { double val = 0; 
        // ... lengthy code 
        return val;
    });
}
在匿名方法中的所执行的内容都是在另外一个线程中进行的。这也会引起一个问题:它不能访问UI对象。然后,你可以按照下面的代码来访问这个方法:

double value = await BigJobAsync(22, 33);


如果,BigJobAsync中的匿名方法包含了await操作,那么需要将匿名方法标记为async:

Task<double> BigJobAsync(int arg1, int arg2) 
{
    return Task.Run<double>(async () => 
    { double val = 0; 
        // ... lengthy code 
        return val;
    });
}


在后面的章节中,我会详细介绍异步处理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: