John P.
John P.

Reputation: 1249

File create blocking UWP from loading

UWP is way over my head and sorry for this question.

Why is a file create blocking my UWP from loading?

public static async Task CreateFile()
{
    StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
    var item = await ApplicationData.Current.LocalFolder.TryGetItemAsync("sFile.xml");
    if (item == null)
    {
        StorageFile file = await storageFolder.CreateFileAsync("sFile.xml");
        await FileIO.WriteLinesAsync(file, GlobalVars.fileStrings);
    }
}

This function is called from my main method

The CreateFile function never returns. Why is that?

Edit: Added main method

public GroupedItemsPage()
{
    this.InitializeComponent();
    this.navigationHelper = new NavigationHelper(this);
    this.navigationHelper.LoadState += navigationHelper_LoadState;
    try
    {
        SampleDataSource.CreateFile().Wait();
        Debug.WriteLine("Continue");
    }
    catch (Exception ex)
    {
        var msg = new MessageDialog(ex.StackTrace);
        Task.Run(async () => { await msg.ShowAsync(); }).Wait();
        throw ex.InnerException;
    }
    GlobalVars.LastFreeSignalCheckTimer.Tick += SampleDataSource.LastFreeSignalCheckTimer_Tick;
    GlobalVars.LastFreeSignalCheckTimer.Interval = new TimeSpan(0, 0, 0, 120);
    GlobalVars.LastFreeSignalCheckTimer.Start();
}

Upvotes: 0

Views: 177

Answers (2)

mm8
mm8

Reputation: 169270

You are running into a deadlock. That's why you should never block on async code.

Instead of calling the async CreateFile method in the constructor of the Page, which is bad practice, you could call it once the page has been initialized by handling the Loaded event of the page. Then you can await the async methods as you should:

public sealed partial class GroupedItemsPage : Page
{
    public GroupedItemsPage()
    {
        this.InitializeComponent();
        this.navigationHelper = new NavigationHelper(this);
        this.navigationHelper.LoadState += navigationHelper_LoadState;
        this.Loaded += GroupedItemsPage_Loaded;
    }

    private async void GroupedItemsPage_Loaded(object sender, RoutedEventArgs e)
    {
        try
        {
            await SampleDataSource.CreateFile();
            Debug.WriteLine("Continue");
        }
        catch (Exception ex)
        {
            var msg = new MessageDialog(ex.StackTrace);
            await msg.ShowAsync();
            throw ex.InnerException;
        }
        GlobalVars.LastFreeSignalCheckTimer.Tick += SampleDataSource.LastFreeSignalCheckTimer_Tick;
        GlobalVars.LastFreeSignalCheckTimer.Interval = new TimeSpan(0, 0, 0, 120);
        GlobalVars.LastFreeSignalCheckTimer.Start();
    }
}

Upvotes: 1

ctron
ctron

Reputation: 694

I think the problem is the .Wait() from your SampleDataSource.CreateFile().Wait(); use await SampleDataSource.CreateFile(); instead.

Wait() is a blocking operation you must be careful if you want to use it because you can easy build a deadlock. In most situations await is the better choice.

In this case you are blocking the UI thread with your Wait() so that the successful execution of the CreateFile() method in the same thread is prevented. With an await instead your code should work because the thread is not blocked while you wait so that other code (like your CreateFile()) can be executed.

Another solution is to use Task.Run to execute the method in background so that you can wait with Wait() because the method is not executed in the same blocked thread (but it would still be ugly code design to block the whole UI thread).

Upvotes: 2

Related Questions