Solved

file accessing problem in multi threading

Posted on 2007-12-05
17
338 Views
Last Modified: 2013-11-07
hi,

i have a asp.net application , when application starts a dedicated thread is started to check if a file is there. if not create it.

2. my aspx page do the appending on that file.
my process is quad core. when i start the application both the thread try to create and append simultanously. so file is used by another process problem is there.

can any
--------------------- in global .aspx-------------------------------

protected void Application_Start(Object sender, EventArgs e)

		{

            try

            {

                ThreadStart job = new ThreadStart(FileNameGenerator.CreateMove);

                Thread thread = new Thread(job);

                thread.Name = "Moniter_Log";

                thread.Start();

            }

            catch (Exception ex)

            {

            

                        }
 

		}

--------------

method being called in abovet thread-----------------

 public static void CreateMove()

{

     string FileName = path+DateTime.Now.ToString("dd_MM_yyyy_HH")+".txt";
 

     while (true)

     {

         try

         {
 

             String[] files = Directory.GetFiles(path);

             if (!File.Exists(FileName) && files.Length > 0)

             {

                 string oldPath = ConfigurationManager.AppSettings["FilePath2"];

                 foreach (string file in files)

                     File.Move(file, file.Replace(path, oldPath));
 

                 FileStream stream = new FileStream(FileName, FileMode.Append, FileAccess.ReadWrite,FileShare.Write);

                // File.Create(FileName);
 

             }

             else if (!File.Exists(FileName))

             {

                 FileStream stream = new FileStream(FileName, FileMode.Append, FileAccess.ReadWrite, FileShare.Write);
 

             }

         }
 
 

         catch (Exception ex)

         {

         }

         finally

         {

             Thread.Sleep(1000 * 60 * 1);

         }

     }

 }

-------------------------------------------------------------------

in aspx page

 protected void Page_Load(object sender, EventArgs e){

public void Write(string Text,string FileName)

        {

            while (!File.Exists(FileName))

                Thread.Sleep(200);

           lock(this)

           {
 

               FileStream stream = new FileStream(FileName, FileMode.Append, FileAccess.ReadWrite);

               StreamWriter writer = new StreamWriter(stream);

           //StreamWriter objStreamWriter1 = File.AppendText(FileName);

           writer.WriteLine(Text);

           writer.Close();

       }

       }}
 

-------------------------------------------------------------

Open in new window

0
Comment
Question by:sitg
  • 13
  • 3
17 Comments
 
LVL 40

Expert Comment

by:evilrix
ID: 20414010
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20414042
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20414049
0
 
LVL 40

Assisted Solution

by:evilrix
evilrix earned 500 total points
ID: 20414100
Basically, you need to ensure that access to the file is mutually exclusive in both threads so that it can only be used by one thread at a time. You normally do this using a thread synchronization primitive such as a Mutex. The mutex object has ownership semantics. It's like having a group of people and only the one holding the red flag can speak. So, a thread will try to take ownership of the mutex and if it can it is allowed to access the resource, else it waits (blocks) on the mutex until whoever does own it gives up ownership. The links I've posted above and below should provide you all the info you need to do this.

http://msdn.microsoft.com/msdnmag/issues/03/01/NET/
http://msdn.microsoft.com/msdnmag/issues/04/09/BasicInstincts/

There's a lot to read but multi-threaded programming can be tricky -- there are no short-cuts. You are better off taking the time to read and understand these articles so as to ensure you fully understand what you are doing here. For this reason I have not attempted to provide code to fix this for you. If I did and it went wrong you'd have no idea how to fix it (or how to diagnose it) and as such you are better off understanding and fixing for yourself :)
0
 

Author Comment

by:sitg
ID: 20414333
hi evilrix:

it will be nice of you ,  if you give a fix of this code .
because i have very less time right now.

i will read on getting the time.

Thanx
0
 
LVL 40

Accepted Solution

by:
evilrix earned 500 total points
ID: 20414371
Ok, this is untested (I have no way of testing it) but it's something like this...
// CREATE MUTEX

// Needs to live somewhere ALL threads can see it

static Mutex mtx = new Mutex();
 

--------------------- in global .aspx-------------------------------

protected void Application_Start(Object sender, EventArgs e)

		{

            try

            {

                ThreadStart job = new ThreadStart(FileNameGenerator.CreateMove);

                Thread thread = new Thread(job);

                thread.Name = "Moniter_Log";

                thread.Start();

            }

            catch (Exception ex)

            {

            

                        }

 

		}

--------------method being called in abovet thread-----------------

 public static void CreateMove()

{

     string FileName = path+DateTime.Now.ToString("dd_MM_yyyy_HH")+".txt";

 

     while (true)

     {

         try

         {

             mtx.WaitOne(); // LOCK MUTEX

 

             String[] files = Directory.GetFiles(path);

             if (!File.Exists(FileName) && files.Length > 0)

             {

                 string oldPath = ConfigurationManager.AppSettings["FilePath2"];

                 foreach (string file in files)

                     File.Move(file, file.Replace(path, oldPath));

 

                 FileStream stream = new FileStream(FileName, FileMode.Append, FileAccess.ReadWrite,FileShare.Write);

                // File.Create(FileName);

 

             }

             else if (!File.Exists(FileName))

             {

                 FileStream stream = new FileStream(FileName, FileMode.Append, FileAccess.ReadWrite, FileShare.Write);

 

             }
 

             mtx.ReleaseMutex(); // UNLOCK MUTEX

         }

 

 

         catch (Exception ex)

         {

         }

         finally

         {

             Thread.Sleep(1000 * 60 * 1);

         }

     }

 }

-------------------------------------------------------------------

in aspx page

 protected void Page_Load(object sender, EventArgs e){

public void Write(string Text,string FileName)

        {

            while (!File.Exists(FileName))

                Thread.Sleep(200);

           lock(this)

           {

              mtx.WaitOne(); // LOCK MUTEX

 

           FileStream stream = new FileStream(FileName, FileMode.Append, FileAccess.ReadWrite);

               StreamWriter writer = new StreamWriter(stream);

           //StreamWriter objStreamWriter1 = File.AppendText(FileName);

           writer.WriteLine(Text);

           writer.Close();
 

           mtx.ReleaseMutex(); // UNLOCK MUTEX

       }

       }}

 

-------------------------------------------------------------

Open in new window

0
 
LVL 40

Assisted Solution

by:evilrix
evilrix earned 500 total points
ID: 20414384
^^^Look for the Mutex I've added, called mtx, which needs to be visible to all threads and locked (WaitOne) before file access and unlocked (ReleaseMutex) after you finish accessing the file in ALL threads.
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20414432
0
3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

 
LVL 40

Expert Comment

by:evilrix
ID: 20414550
The code below is a working example of how a mutex synchronizes threads. Without it the output is a mess. With it each thread outputs 10 lines and then defers to the other. To see the difference comment out the bits I've noted in the code
using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Text.RegularExpressions;

using System.Threading;
 
 

namespace cs_console

{

    class Program

    {

        static bool bQuit = false;

        static Mutex mtx = new Mutex(false);
 

        static void ThreadFunc()

        {

            while (!bQuit)

            {

                for (int x = 0; x < 10; ++x)

                {

                    //////////////////////////////////////////////////

                    // Comment out to see what it's like with no mutex

                    mtx.WaitOne();

                    //////////////////////////////////////////////////

                    for (int y = 0; y < 10; ++y)

                    {

                        Console.WriteLine("In thread: " + y.ToString());

                        Thread.Sleep(0);

                    }

                    //////////////////////////////////////////////////

                    // Comment out to see what it's like with no mutex

                    mtx.ReleaseMutex();

                    //////////////////////////////////////////////////

                }

            }

        }

        static void Main(string[] args)

        {

            Thread thread = new Thread(new ThreadStart(Program.ThreadFunc));

            thread.Start();
 

            for (int x = 0; x < 10; ++x)

            {

                //////////////////////////////////////////////////

                // Comment out to see what it's like with no mutex

                mtx.WaitOne();

                //////////////////////////////////////////////////

                for (int y = 0; y < 10; ++y)

                {

                    Console.WriteLine("In main: " + y.ToString());

                    Thread.Sleep(0);

                }

                //////////////////////////////////////////////////

                // Comment out to see what it's like with no mutex

                mtx.ReleaseMutex();

                //////////////////////////////////////////////////

            }
 

            bQuit = true;
 

            thread.Join();

        }

    }

}

Open in new window

0
 

Author Comment

by:sitg
ID: 20414565
thanks,
but i have question.
if the both threads runs simultaneosly on two processors.

because if at same time both request for
  mtx.WaitOne();

will it work ...
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20414584
Yes, only one will win and the other will block. This object is designed to be used in this way.
0
 
LVL 40

Assisted Solution

by:evilrix
evilrix earned 500 total points
ID: 20414596
Of course, you won't know which will win -- that'll be non-deterministic.
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20414608
If you need to synchronize this is some way you can either create the mutex so the thread creating it has initial ownership or you can use an AutoResetEvent to synchronize this ion some way.

http://msdn2.microsoft.com/en-us/library/system.threading.autoresetevent.aspx
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20414750
The following example uses 2 auto reset events to pass signals between main and thread. Comments in the code should clarify what is going on: -
using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Text.RegularExpressions;

using System.Threading;
 
 

namespace cs_console

{

    class Program

    {

        static bool bQuit = false;

        static Mutex mtx = new Mutex(false);

        static AutoResetEvent autoEventThread = new AutoResetEvent(false);

        static AutoResetEvent autoEventMain = new AutoResetEvent(false);
 

        static void ThreadFunc()

        {

            while (!bQuit)

            {

                for (int x = 0; x < 10; ++x)

                {

                    //////////////////////////////////////////////////////

                    // Wait for main to signal

                    autoEventThread.WaitOne();

                    //////////////////////////////////////////////////////
 

                    if (!bQuit)

                    {

                        //////////////////////////////////////////////////

                        // Comment out to see what it's like with no mutex

                        mtx.WaitOne();

                        //////////////////////////////////////////////////

                        for (int y = 0; y < 10; ++y)

                        {

                            Console.WriteLine("In thread: " + y.ToString());

                            Thread.Sleep(0);

                        }

                        //////////////////////////////////////////////////

                        // Comment out to see what it's like with no mutex

                        mtx.ReleaseMutex();

                        //////////////////////////////////////////////////

                        // Signal main

                        autoEventMain.Set();

                        //////////////////////////////////////////////////

                    }

                }

            }

        }

        static void Main(string[] args)

        {

            Thread thread = new Thread(new ThreadStart(Program.ThreadFunc));

            thread.Start();
 

            for (int x = 0; x < 10; ++x)

            {

                //////////////////////////////////////////////////

                // Use event to ensure main runs before thread

                // and do two main loops to one thread loop

                if ((x > 0) && (x % 2) == 0)

                {

                    // Signal thread

                    autoEventThread.Set();

                    // Wait for thread to signal

                    autoEventMain.WaitOne();

                }

                //////////////////////////////////////////////////

                // Comment out to see what it's like with no mutex

                mtx.WaitOne();

                //////////////////////////////////////////////////

                for (int y = 0; y < 10; ++y)

                {

                    Console.WriteLine("In main: " + y.ToString());

                    Thread.Sleep(0);

                }

                //////////////////////////////////////////////////

                // Comment out to see what it's like with no mutex

                mtx.ReleaseMutex();

                //////////////////////////////////////////////////

            }
 

            bQuit = true;
 

            //////////////////////////////////////////////////////

            // Signal thread

            autoEventThread.Set();

            //////////////////////////////////////////////////////
 

            thread.Join();

        }

    }

}

Open in new window

0
 
LVL 40

Assisted Solution

by:evilrix
evilrix earned 500 total points
ID: 20414976
Ensure your code is exception safe by using a try/finally block to ensure the mutex is always freed, even if there is an exception throw: -
using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Text.RegularExpressions;

using System.Threading;

 

 

namespace cs_console

{

    class Program

    {

        static bool bQuit = false;

        static Mutex mtx = new Mutex(false);

 

        static void ThreadFunc()

        {

            while (!bQuit)

            {

                for (int x = 0; x < 10; ++x)

                {

                    if (!bQuit)

                    {

                        try

                        {

                            //////////////////////////////////////////////////

                            // Comment out to see what it's like with no mutex

                            mtx.WaitOne();

                            //////////////////////////////////////////////////

                            for (int y = 0; y < 10; ++y)

                            {

                                Console.WriteLine("In thread: " + y.ToString());

                                Thread.Sleep(0);

                            }

                            //////////////////////////////////////////////////

                        }

                        finally

                        {

                            //////////////////////////////////////////////////

                            // Comment out to see what it's like with no mutex

                            mtx.ReleaseMutex();

                            //////////////////////////////////////////////////

                        }

                    }

                }

            }

        }

        static void Main(string[] args)

        {

            Thread thread = new Thread(new ThreadStart(Program.ThreadFunc));

            thread.Start();

 

            for (int x = 0; x < 10; ++x)

            {

                try

                {

                    //////////////////////////////////////////////////

                    // Comment out to see what it's like with no mutex

                    mtx.WaitOne();

                    //////////////////////////////////////////////////

                    for (int y = 0; y < 10; ++y)

                    {

                        Console.WriteLine("In main: " + y.ToString());

                        Thread.Sleep(0);

                    }

                    //////////////////////////////////////////////////

                }

                finally

                {

                    //////////////////////////////////////////////////

                    // Comment out to see what it's like with no mutex

                    mtx.ReleaseMutex();

                    //////////////////////////////////////////////////

                }

            }

 

            bQuit = true;

 

            thread.Join();

        }

    }

} 

Open in new window

0
 
LVL 1

Expert Comment

by:uggel
ID: 20416016
Hello sitg,

about the two processor question.

The definition of a thread is that it is a "subprocess" within a process that share memory with the other subprocesses. That way the address to the semaphore/mutex is the same in all threads within that process. Your quad cores also share cache physically which makes things fast and easy. Compare this to actually having 4 SIMD-coupled procs on a quad proc mother board.
0
 

Author Comment

by:sitg
ID: 20418312
evilrix:

it is not working i just  put the mutex object in the global.asax. which is visible to all.
and rest of the code as you given
put same file access problem is occuring. or safe handle has been closed problem
0

Featured Post

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Just a quick little trick I learned recently.  Now that I'm using jQuery with abandon in my asp.net applications, I have grown tired of the following syntax:      (CODE) I suppose it just offends my sense of decency to put inline VBScript on a…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
In this video I am going to show you how to back up and restore Office 365 mailboxes using CodeTwo Backup for Office 365. Learn more about the tool used in this video here: http://www.codetwo.com/backup-for-office-365/ (http://www.codetwo.com/ba…
Internet Business Fax to Email Made Easy - With  eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, f…

910 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now