Ortund
Ortund

Reputation: 8255

How to wait for a stream to finish writing to a file before reading it

My code is pretty simple; it uses a StringBuilder and a FileStream to write data to a text file and then [optionally] opens the text file for viewing:

public async Task ExportData(data)
{
    var sb = new StringBuilder();
    sb.AppendLine(BuildStringFromData());

    var dir = $@"C:\Ortund\xExports\{DateTime.Now.Date.ToString
        ("yyyy-MM-dd", CultureInfo.InvariantCulture)}";
    var fullPath = $@"{dir}\{filename}.txt";

    var stream = new FileStream(fullPath, FileMode.CreateNew, FileAccess.ReadWrite);

    var bytes = Encoding.UTF8.GetBytes(sb.ToString());
    await stream.WriteAsync(bytes, 0, bytes.Length);

    if (MessageBox.Show("Open the file?", "Open?", MessageBoxButton.YesNo)
        == MessageBoxResult.Yes)
    {
        System.Diagnostics.Process.Start(fullPath);
    }
}

I awaited the write operation in the file stream thinking this would pause execution of this particular method until all the bytes had been written but that isn't what's happening.

What's happening is that the prompt to open the file is coming up immediately and when I open it, its blank. Notepad++ only informs me a few seconds later that changes have been made to the file and asks me if I want to reload it whereupon I see the data that was exported.

How can I make execution wait until the file data is completely written before asking the user to open the file?

Upvotes: 0

Views: 3616

Answers (1)

Ortund
Ortund

Reputation: 8255

I overlooked the obvious on this one...

As per comment on the question by @Evk, I put the FileStream into a using block, but I also moved it to a new method which takes the data and file path as parameters:

private async Task WriteDataToFile(List<ViewModel> data, string path)
{
    using (var fs = new FileStream(path, FileMode.CreateNew, FileAccess.ReadWrite))
    {
        var sb = new StringBuilder();
        // Loop through the data and build the string.

        var bytes = Encoding.UTF8.GetBytes(sb.ToString());
        await fs.WriteAsync(bytes, 0, bytes.Length);
    }
}

The using closes the FileStream which is what I overlooked.

Upvotes: 1

Related Questions