0
votes

I am developing a windows 8.1 app for the first time and running it (debugging mode) within visual studio 2013 as I develop.

I have a main .xaml page with a frame containing my menu (listview) and another frame containing the page that user has selected at that moment.

When my page2 loads it writes to a file in storage and then reads the value, this is my proof of concept for basic reading and writing of data.

The first time page2 loads everything works ok, but the second time the file is still locked and it throws the following error in WriteTimeStamp():

Error:

An exception of type 'System.IO.FileLoadException' occurred in mscorlib.dll but was not handled in user code

Additional information: The process cannot access the file because it is being used by another process. (Exception from HRESULT: 0x80070020)

Code Snippets

//Main.Xaml - showing the layout
<Grid>
    <Frame x:Name="BasicLayout" Grid.Column="0">
        <ListView>
            <!--  Menu items... -->
        </ListView>
    </Frame>
    <Frame x:Name="SpecificLayout" Grid.Column="1">

    </Frame>

</Grid>

    // Main Page navigation logic
    void itemListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        ListViewItem itemClicked = (ListViewItem)e.AddedItems[0];
        if(itemClicked != null && itemClicked.Tag != null && !string.IsNullOrEmpty(itemClicked.Tag.ToString()))
        {
            switch (itemClicked.Tag.ToString())
            { 
                case "Page1":
                    SpecificLayout.Navigate(typeof(Page1));
                    break;
                case "Page2":
                    SpecificLayout.Navigate(typeof(Page2));
                    break;
                case "Page3":
                    SpecificLayout.Navigate(typeof(Page3));
                    break;
            }
        }
    }

// Page 2 initialisation
public Page2()
    {
        this.InitializeComponent();
        WriteTimestamp();
        ReadTimestamp();
    }
// Page 2 read/write file logic
async void WriteTimestamp()
{
    myTextbox.Text = "saving timestamp";
    Windows.Globalization.DateTimeFormatting.DateTimeFormatter formatter = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter("longtime");
    StorageFile sampleFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("dataFile.txt", CreationCollisionOption.ReplaceExisting);
    await FileIO.WriteTextAsync(sampleFile, formatter.Format(DateTime.Now)); // THIS LINE THROWS THE ERROR
}

async void ReadTimestamp()
{
    try
    {
        StorageFile sampleFile = await ApplicationData.Current.LocalFolder.GetFileAsync("dataFile.txt");
        String timestamp = await FileIO.ReadTextAsync(sampleFile);

        // Data is contained in timestamp
        myTextbox.Text = timestamp;
    }
    catch (Exception)
    {
        // Timestamp not found
    }
}
1
Are You calling this method one below the other?? Doing so has caused problems for me.. Might be the threading issues.Mangesh
You're not disposing the file handle. Use using blocks around your files.MarcinJuraszek
Yes I'm calling write then read, I've updated my question to show this (Page 2 initialisation). What's your suggestion for resolution?John
@MarcinJuraszek I was under the impression that await FileIO.WriteTextAsync() disposed the file stream objects for me? Can you provide a code sample?John
I'm not 100% how it works for Windows App development, but you should make sure that sampleFile doesn't implement IDisposable.MarcinJuraszek

1 Answers

1
votes

You're calling ReadTimeStamp before WriteTimeStamp finishes writing. Async functions return when they reach an await while the awaited Task goes off and does its thing. When the awaited Task completes the function continues on the next statement.

Define WriteTimeStamp as async Task instead of async void so it can be awaited. Since it's void you just need to change WriteTimestamp's return value and (by convention) it's name. You'll also need to move the calls outside of Page2's constructor since the constructor cannot be async.

async Task WriteTimestampAsync()
{
    myTextbox.Text = "saving timestamp";
    Windows.Globalization.DateTimeFormatting.DateTimeFormatter formatter = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter("longtime");
    StorageFile sampleFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("dataFile.txt", CreationCollisionOption.ReplaceExisting);
    await FileIO.WriteTextAsync(sampleFile, formatter.Format(DateTime.Now)); // THIS LINE THROWS THE ERROR
}

...

async void DoTimeStampStuff()
{
    await WriteTimestampAsync();
    await ReadTimestampAsync();
}