views:

43

answers:

4

Hi all. I created and started some Threads that each one writes something to a common text file. but the following error appears to me: "The process cannot access the file 'C:\hello.txt' because it is being used by another process."

void AccessFile()

    {

        int num = 5;

        Thread[] trds = new Thread[5];

        for (int i = 0; i < num; i++)

        {

            trds[i] = new Thread(new ParameterizedThreadStart(WriteToFile));

        }

        for (int i = 0; i < num; i++)

        {

            trds[i].Start(String.Format("{0}: Hello from thread id:#{1}", i, trds[i].ManagedThreadId));

        }

    }





    void WriteToFile(object message)

    {

        string FileName = "C:\\hello.txt";

        string mess = (string)message;

        System.IO.StreamWriter sw = null;

        FileStream objStream = null;

        sw = File.AppendText(FileName);

        if (sw == null)

        {

            objStream = new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);

            sw = new StreamWriter(objStream);

        }

        sw.WriteLine(mess);

        sw.Close();

        sw.Dispose();

    }

the AccessFile() method is the starting point. could any one tell me what should i do?

A: 

What do you expect to happen? Even if you did write to the same file from a number of different threads, what would you acheive? The results would be, at best, undefined.

What are you really trying to acheive?

spender
in fact, i have a multithreaded (containing nested threads) windows application in C# 3.5 (VS 2008). i wanna write the exact time of running code lines in each method just for benchmarking the prformance of my code. i can use System.Diagnostics.Debug.WriteLine() method but i don't like that and wanna have my own file for tracing.
bobby
the tool you need is called a _Profiler_ and i am pretty sure there is one included with Visual Studio. using your own profiling code will be at best inaccurate, since writing to a file as you do involves a lot of overhead and will definitely influence the running time of each thread (especially opening and closing the file each time you write a single line).
Adrien Plisson
@spender: writing to a single file from multiple threads is a pretty common operation, and the resulting file is generally called a "log". if properly protected from concurrent access, the result is not undefined at all.
Adrien Plisson
The key being "if properly protected from concurrent access"
spender
@spender: don't expect a beginner to come with a "properly protected from concurrent access" solution. you will have to guide him through, and your answer was a bit discouraging, implying that it is not possible.
Adrien Plisson
A: 

You could write to that file using a Singleton object with a synchronized lock on it. I'm not at home in c#, but you can only have one instance of the file itself, and you should synchronize access to that file.

extraneon
thanks for your answer, but would you mind please leave me an example?
bobby
A: 

At the very least you need to put a lock at the start of WriteToFile and release it at the end after you've closed it.

Writing to a file should be an atomic operation and requires exclusive access to the resource for the duration of the write.

What you have here is several threads all trying to write to the file at the same time. If this were not the cast at best you'd get the last thread overwriting everything that had come before, at worst you'd get a corrupted file.

ChrisF
A: 

If you're writing to a file, it's only safe to have it open in one place, since the various threads would overwrite eachother's work.

Instead, if multiple threads need to make changes to a single file (such as a database file), you need to force the threads to take turns writing to the file, either by using synchronization objects, or by setting up a single "management" thread that mediates access to the file on behalf of the other threads.

tylerl