Solved

file accessing problem in multi threading

Posted on 2007-12-05
17
346 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
Command Line Tips and Tricks

The command line is a powerful tool at the disposal of every Linux user. Although Linux distros come with beautiful user interfaces, it's worthwhile to learn the command line because it allows you to do a number of things that you otherwise cannot do from the GUI.  

 
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
 
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

Visualize your virtual and backup environments

Create well-organized and polished visualizations of your virtual and backup environments when planning VMware vSphere, Microsoft Hyper-V or Veeam deployments. It helps you to gain better visibility and valuable business insights.

Question has a verified solution.

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

IntroductionWhile developing web applications, a single page might contain many regions and each region might contain many number of controls with the capability to perform  postback. Many times you might need to perform some action on an ASP.NET po…
International Data Corporation (IDC) prognosticates that before the current the year gets over disbursing on IT framework products to be sent in cloud environs will be $37.1B.
In this video we outline the Physical Segments view of NetCrunch network monitor. By following this brief how-to video, you will be able to learn how NetCrunch visualizes your network, how granular is the information collected, as well as where to f…
Michael from AdRem Software explains how to view the most utilized and worst performing nodes in your network, by accessing the Top Charts view in NetCrunch network monitor (https://www.adremsoft.com/). Top Charts is a view in which you can set seve…

623 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