简体   繁体   English

如何在UWP中等待FileOpenPicker的异步方法?

[英]How do I wait on async method in UWP for FileOpenPicker?

I wanted to create some simple practice code in UWP that opens up a text file, then immediately appends that code with trivial text. 我想在UWP中创建一些简单的练习代码,该代码打开一个文本文件,然后立即在代码中附加一些琐碎的文本。

public MainPage()
{
    this.InitializeComponent();

    OpenFile();
    SaveFile();
}

public async void OpenFile()
{
    FileOpenPicker picker = new FileOpenPicker();
    picker.SuggestedStartLocation = PickerLocationId.Desktop;
    picker.FileTypeFilter.Add(".txt");

    DataFile = await picker.PickSingleFileAsync();
    if (DataFile == null) { return; }
}

public async void SaveFile()
{
    await FileIO.AppendTextAsync(DataFile, "" + DateTime.Now + "\n");
}

private StorageFile DataFile { get; set; }

As expected, this code returns an error since in SaveFile() method, since SaveFile() runs immediately after OpenFile() and since OpenFile() has not completed its operation of retrieving the target file for SaveFile() to use. 如预期的那样,此代码返回错误,因为在SaveFile()方法中,因为SaveFile()在OpenFile()之后立即运行,并且因为OpenFile()尚未完成其获取要使用的File的目标文件的操作。 The thing is, when I try to modify the following code in OpenFile, I receive an AggregateException error: 问题是,当我尝试在OpenFile中修改以下代码时,我收到一个AggregateException错误:

DataFile = picker.PickSingleFileAsync();
Task task = Task.Run( async() => DataFile = await picker.PickSingleFileAsync() );
task.Wait();

I was wondering how I can block OpenFile() until it is done retrieving the target file, before SaveFile() runs. 我想知道如何在SaveFile()运行之前阻止OpenFile()直到完成对目标文件的检索。

The constructor of a class should be fast and definitely shouldn't have any async methods. 类的构造函数应该是快速的,并且绝对不应具有任何异步方法。 In your case you have been firing those methods as fire-forget , there is a race condition, where you haven't picked a file and you try to save to it. 在您的情况下,您一直将这些方法作为fire-forget触发,这是一个竞争条件,您没有选择文件,而是尝试将其保存。 Nothing good comes from that. 没有任何好处。

Instead if you want a user to do soemthing once your MainPage is created, you may for example use Loaded event for this: 相反,如果您希望用户在创建MainPage之后就这样做,那么您可以为此使用Loaded事件:

public MainPage()
{
    this.InitializeComponent();
    this.Loaded += LoadedHandler;
}

private async void LoadedHandler(object sender, RoutedEventArgs e)
{
    // assume that we want to do this only once
    this.Loaded -= LoadedHandler;
    await OpenFile();
    await SaveFile();
}

public async Task OpenFile()
{
    FileOpenPicker picker = new FileOpenPicker();
    picker.SuggestedStartLocation = PickerLocationId.Desktop;
    picker.FileTypeFilter.Add(".txt");

    DataFile = await picker.PickSingleFileAsync();
    if (DataFile == null) { return; }
}

public async Task SaveFile()
{
    await FileIO.AppendTextAsync(DataFile, "" + DateTime.Now + "\n");
}

private StorageFile DataFile { get; set; }

Note also that I've changed your methods to Tasks - you should avoid async void . 另请注意,我已将您的方法更改为“ 任务” -您应避免使用异步void

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM