简体   繁体   中英

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.

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. The thing is, when I try to modify the following code in OpenFile, I receive an AggregateException error:

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.

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. 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:

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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