?
Solved

file accessing problem in multi threading

Posted on 2007-12-05
17
Medium Priority
?
348 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Prepare for your VMware VCP6-DCV exam.

Josh Coen and Jason Langer have prepared the latest edition of VCP study guide. Both authors have been working in the IT field for more than a decade, and both hold VMware certifications. This 163-page guide covers all 10 of the exam blueprint sections.

 
LVL 40

Assisted Solution

by:evilrix
evilrix earned 2000 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 2000 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 2000 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
 
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 2000 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 2000 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

Prepare for your VMware VCP6-DCV exam.

Josh Coen and Jason Langer have prepared the latest edition of VCP study guide. Both authors have been working in the IT field for more than a decade, and both hold VMware certifications. This 163-page guide covers all 10 of the exam blueprint sections.

Question has a verified solution.

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

Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
This article shows how to deploy dynamic backgrounds to computers depending on the aspect ratio of display
This course is ideal for IT System Administrators working with VMware vSphere and its associated products in their company infrastructure. This course teaches you how to install and maintain this virtualization technology to store data, prevent vuln…
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…

719 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