Search code examples
c#windows-runtimewinrt-xamlwindows-store-appswinrt-async

File access from a background task in a windows store app


I can't seem to read a file from a background task in a windows store app. Here's the code that reads the file content:

async private static Task<string> ReadAsync(string FileName)
{
    var folder = ApplicationData.Current.LocalFolder;
    var file = await folder.GetFileAsync(FileName);
    Windows.Storage.Streams.IRandomAccessStreamWithContentType inputStream = null;
    try
    {
        inputStream = await file.OpenReadAsync();
    }
    catch (Exception ex)
    {
        throw (ex);
    }
    string content = string.Empty;
    using (Stream stream = inputStream.AsStreamForRead())
    {
        using (StreamReader reader = new StreamReader(stream))
        {
            try
            {
                // *** program exits on this line
                content = await Task.Run(() => reader.ReadToEnd());
            }
            catch(Exception ex)
            {
                // no error is caught
                content = ex.Message;
            }
        }
    }

    return content;
}

The program exits on the line that calls ReadToEnd() on the StreamReader - no error is caught in the try catch block. In the output window I get:

The program '[8968] backgroundTaskHost.exe: Managed (v4.0.30319)' has exited with code 1 (0x1)

Is it possible to access files a background task? If so, where am I going wrong?


Solution

  • It would be helpful if you posted your IBackgroundTask code. Without seeing it I suspect you didn't call GetDeferral() inside it, e.g.:

    public async void Run(IBackgroundTaskInstance taskInstance)
    {
        var deferral = taskInstance.GetDeferral();
        var contents = await ReadAsync("MyFile.txt");
        deferral.Complete();
    }
    

    You need to call GetDeferral() whenever you are making asynchronous calls inside your background task. This way you tell the runtime it needs to wait for the asynchronous call to complete and not stop the background task as soon as Run exits.

    Once you're done, i.e. usually at the end of your Run method, you need to call Complete() on the deferral instance to notify the runtime that you're done.