Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When using FileStream.WriteAsync() what happens when the method is called again

I am recording a video stream to disk. For this I use the following code:

private async Task SaveToFile(IntPtr data, Int32 size)
{
    if (_FileStream == null) return;
    Byte[] buf = new Byte[size];
    Marshal.Copy(data, buf, 0, size);
    //dont await here - just continue
    _FileStream.WriteAsync(buf, 0, size);
}

So far it seems to work without issue. What I just want to confirm is what happens if this method is called before the previous iteration has finished.

You will notice I don't await on the WriteAsync() call. I'm not sure if this is correct, but the API I am using states to keep operations to a minimum inside this method, so as to not block the callback internally in the API. This seems like to correct thing to do, simply pass the data to the stream, and return immediately.

Can someone please confirm what happens if the last WriteAsync() call hasn't finished, and I call WriteAsync() again? Or should I be awaiting the WriteAsync() call?

EDIT: I am yet to experience exceptions using the above method, so I guess my last question is are there any repercussions when using WriteAsync() from inside an external DLL callback? The DLL is a third party Directshow component. I cannot verify how it internally works, but it simply provides me with data via a callback, in which i save to the filestream.

like image 739
Simon Avatar asked Feb 20 '15 06:02

Simon


People also ask

What does WriteAsync do?

WriteAsync(Char[], Int32, Int32)Asynchronously writes a subarray of characters to the stream.

What does FileStream do?

Remarks. Use the FileStream class to read from, write to, open, and close files on a file system, and to manipulate other file-related operating system handles, including pipes, standard input, and standard output.

How FileStream works in c#?

The FileStream is a class used for reading and writing files in C#. It is part of the System.IO namespace. To manipulate files using FileStream, you need to create an object of FileStream class. This object has four parameters; the Name of the File, FileMode, FileAccess, and FileShare.


1 Answers

There is nothing wrong with asynchronous overlapping WriteAsync operations, as long as they write to different, non-overlapping segments of the file:

using System;
using System.Linq;
using System.Threading.Tasks;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            var tempFile = System.IO.Path.GetTempFileName();
            Console.WriteLine(tempFile);

            var fs = new System.IO.FileStream(
                tempFile, 
                System.IO.FileMode.Create, 
                System.IO.FileAccess.ReadWrite, 
                System.IO.FileShare.ReadWrite, 
                bufferSize: 256,
                useAsync: true);

            fs.SetLength(8192);

            var buff1 = Enumerable.Repeat((byte)0, 2048).ToArray();
            var buff2 = Enumerable.Repeat((byte)0xFF, 2048).ToArray();

            try
            {
                fs.Seek(0, System.IO.SeekOrigin.Begin);
                var task1 = fs.WriteAsync(buff1, 0, buff1.Length);

                fs.Seek(buff1.Length, System.IO.SeekOrigin.Begin);
                var task2 = fs.WriteAsync(buff2, 0, buff2.Length);

                Task.WhenAll(task1, task2).Wait();
                Console.ReadLine();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
    }
}

On the low level, it all comes down to WriteFile API with non-null LPOVERLAPPED lpOverlapped, which is a supported scenario in Windows API.

If the writes do overlap, you still won't see an error, but the writes will race and the end result may be unpredictable.

like image 140
noseratio Avatar answered Nov 04 '22 07:11

noseratio