reading and writing file using autoresetevent in C#

811 views Asked by At

I have written a simple program of thread synchronization. But when I run this program I get an error "The process cannot access the file 'D:\Vivek.txt' because it is being used by another process." Why I am getting this error.

class Program
{
    const string Filepath = "D:\\Vivek.txt";
    static AutoResetEvent writerwaithandle= new AutoResetEvent(true);// Signaled state
    static AutoResetEvent readerwaithandle = new AutoResetEvent(false);

    static void Main()
    {

        if (File.Exists(Filepath))
        {
            File.Delete(Filepath);                                          
        }

        File.CreateText(Filepath);
        CreateWriterThread();
        CreateReaderThread();
        Console.ReadKey();
    }

    private static void CreateWriterThread()
    {
        for (int i = 1; i <= 10;i++ )
        {

            var thread = new Thread(WriteFile);
            thread.Name = "Writer " + i;
            thread.Start();
            Thread.Sleep(250);
        }

    }

    private static void CreateReaderThread()
    {
        for (int i = 1; i <= 10; i++)
        {
            var thread = new Thread(ReadFile);
            thread.Name = "Reader " + i;
            thread.Start();
        }
    }

    private static void WriteFile()
    {
        writerwaithandle.WaitOne();

        var stream = new FileStream(Filepath, FileMode.Append);
        var streamwriter = new StreamWriter(stream);
        streamwriter.WriteLine("written by"+Thread.CurrentThread.Name+DateTime.Now));
        streamwriter.Flush();
        streamwriter.Close();

        readerwaithandle.Set();
    }

    private static void ReadFile()
    {
        readerwaithandle.WaitOne();
        if (File.Exists(Filepath))
        {
            var stream = new FileStream(Filepath, FileMode.Open);
            var streamreader = new StreamReader(stream);
            var text = streamreader.ReadToEnd();
            streamreader.Close();
            Console.WriteLine("Read by thread {0} \n",Thread.CurrentThread.Name);
            Console.WriteLine(text);
        }
        writerwaithandle.Set();
    }
}

when I replace the code from

if (File.Exists(Filepath))
{
  File.Delete(Filepath);                                          
}
  File.CreateText(Filepath);

to

if (!File.Exists(Filepath))
{
  File.CreateText(Filepath);
}

the program shows the same error for first time. after that it never gives any error. please anyone tell me the bug area, reason and what should be the best solution.

2

There are 2 answers

0
Srinivas On

When you use FileStream always use it with using like

using (var fileStream = new FileStream(Filepath, FileMode.Open))
{
   Your code...
}

This ensures that the stream gets disposed properly.

You can also use the StreamReader along with using

using (var fileStream = new FileStream(Filepath, FileMode.Open))
{
    using (var reader = new StreamReader(stream))
    {
        Your code...
    }
}
1
testCoder On

Be vigilant, look at the documentation of File.CreateText

Creates or opens a file for writing UTF-8 encoded text.

Return Value Type: System.IO.StreamWriter A StreamWriter that writes

to the specified file using UTF-8 encoding

It means that there is no need to create a new FileStream because FileStream is already created and returned when you use File.CreateText. You should only use that created FileStream in your code.

Here is the fixed version of your code:

 class Program
    {
        const string Filepath = "D:\\Vivek.txt";
        static AutoResetEvent writerwaithandle = new AutoResetEvent(true);// Signaled state
        static AutoResetEvent readerwaithandle = new AutoResetEvent(false);

        static void Main()
        {

            if (File.Exists(Filepath))
            {
                File.Delete(Filepath);
            }

            //File.CreateText(Filepath);
            CreateWriterThread();
            CreateReaderThread();
            Console.ReadKey();
        }

        private static void CreateWriterThread()
        {
            for (int i = 1; i <= 10; i++)
            {

                var thread = new Thread(WriteFile);
                thread.Name = "Writer " + i;
                thread.Start();
                Thread.Sleep(250);
            }

        }

        private static void CreateReaderThread()
        {
            for (int i = 1; i <= 10; i++)
            {
                var thread = new Thread(ReadFile);
                thread.Name = "Reader " + i;
                thread.Start();
            }
        }

        private static void WriteFile()
        {
            writerwaithandle.WaitOne();


            var streamwriter = File.CreateText(Filepath);

            //var stream = new FileStream(Filepath, FileMode.Append);
            //var streamwriter = new StreamWriter(stream);
            streamwriter.WriteLine("written by" + Thread.CurrentThread.Name + DateTime.Now);
            streamwriter.Flush();
            streamwriter.Close();

            readerwaithandle.Set();
        }

        private static void ReadFile()
        {
            readerwaithandle.WaitOne();
            if (File.Exists(Filepath))
            {
                var stream = new FileStream(Filepath, FileMode.Open);
                var streamreader = new StreamReader(stream);
                var text = streamreader.ReadToEnd();
                streamreader.Close();
                Console.WriteLine("Read by thread {0} \n", Thread.CurrentThread.Name);
                Console.WriteLine(text);
            }
            writerwaithandle.Set();
        }
    }