简体   繁体   中英

Restricting the instance of a process to 1 in C#

I currently have a big problem, the code below checks for the keyword "mp4:production/CATCHUP/" in a file, and if found it will launch an executable, although because it finds multiple (exactly the same) instances of "mp4:production/CATCHUP/" it launches several processes. Is there anyway of restricting this, so that it may stop looking when found one instance?

My code is as follows:

string s = "";
        private void CheckLog()
        {
            bool _found;
            while (true)
            {
                _found = false;
                Thread.Sleep(5000);
                if (!System.IO.File.Exists("Command.bat")) continue;
                using (System.IO.StreamReader sr = System.IO.File.OpenText("Command.bat"))
                {

                    while ((s = sr.ReadLine()) != null)
                    {
                        if (s.Contains("test"))
                        {
                            _found = true;
                            break;
                        }

                    }
                }
                if (_found)
                {
                    // Deletes filename in the log file, as the filename is instead handled by p.start

                    var result = Regex.Replace(s, @"test", string.Empty);

                    s = result;

                    RemoveEXELog(); // Deletes a specific keyword from Command.bat
                    RemoveHostFile();
                    Process p = new Process();
                    p.StartInfo.WorkingDirectory = "dump";
                    p.StartInfo.FileName = "test.exe";
                    p.StartInfo.Arguments = s;

                    p.Start();
                    p.WaitForExit();

                    MessageBox.Show("Operation Successful!");
                    string myPath = @"dump";
                    System.Diagnostics.Process prc = new System.Diagnostics.Process();
                    prc.StartInfo.FileName = myPath;
                    prc.Start();


                    ClearLog(); // Deletes Command.bat and then creates a new empty Command.bat
                    LogTrue();
                }
            }
        }

For this scenario I would use a Singleton class to manage the workflow. The Singleton would manage the equivalent to your _found variable in a global threadsafe manner. All threads would then query this property.

Something like the following:

public sealed class Singleton
{
   private static volatile Singleton instance;
   private static object syncRoot = new Object();


   private Singleton() {}

   public bool Found { get; set; }

   public static Singleton Instance
   {
      get 
      {
         if (instance == null) 
         {
            lock (syncRoot) 
            {
               if (instance == null) 
                  instance = new Singleton();
            }
         }

         return instance;
      }
   }
}

Then your code would be something like the following:

private void CheckLog()
    {
        //bool _found; //not needed anymore
        while (!Singleton.Instance.Found)
        {
            //_found = false;
            Thread.Sleep(5000);
            if (!System.IO.File.Exists("Command.bat")) continue;
            using (System.IO.StreamReader sr = System.IO.File.OpenText("Command.bat"))
            {

                while ((s = sr.ReadLine()) != null)
                {
                    if (s.Contains("mp4:production/CATCHUP/"))
                    {
                        Singleton.Instance.Found = true;
                        break;
                    }

                }
            }
            if (Singleton.Instance.Found)
            {
                // Deletes filename in the log file, as the filename is instead handled by p.start

                var result = Regex.Replace(s, @"rtmpdump", string.Empty);

                s = result;

                RemoveEXELog(); // Deletes a specific keyword from Command.bat
                RemoveHostFile();
                Process p = new Process();
                p.StartInfo.WorkingDirectory = "dump";
                p.StartInfo.FileName = "test.exe";
                p.StartInfo.Arguments = s;

                p.Start();
                p.WaitForExit();

                MessageBox.Show("Operation Successful!");
                string myPath = @"dump";
                System.Diagnostics.Process prc = new System.Diagnostics.Process();
                prc.StartInfo.FileName = myPath;
                prc.Start();


                ClearLog(); // Deletes Command.bat and then creates a new empty            Command.bat
                LogTrue();
        }
    }
}

As suggested by Hans Passant, what is wrong with the obvious stop looping once you'vre found it approach? No singletons required.

private void CheckLog()
{
    bool found = false;
    while (!found)
    {
        //your code ...
        while ((s = sr.ReadLine()) != null)                     
        {
            if (s.Contains("test"))   
            {
                _found = true;
                break;
            }
        }
        if (found)
        {
            //some more of your code ...
        }
        else
        {
            //get ready for the next iteration
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM