0

I think it's fairly simple task, but I really can't find good answer for that. I have a class/method that downloads files from different server, processes them, and makes changes to database. The problem is that, it can be manually launched by administrators, and I want to prevent from multiple instances of this process running at the same time. Is there any easy way to achieve that?

Stablo
  • 91
  • 10
  • There are a lot of ways, but which one is best will probably depend somewhat on your code and your specific requirements. For example, if N administrators launch the process at around the same time, do you want them all to wait for the process that's underway, and see the same results when it finishes? Or do you want all but the first to receive an error saying the process is underway? Or do you want to run the process N times, but put them all in a queue to wait their turn for their action to execute? – StriplingWarrior Feb 29 '20 at 16:42
  • Please, share what have you tried so far and your code. If you need it only in one server, you can make your process single instance – Pavel Anikhouski Feb 29 '20 at 16:46
  • See this: https://stackoverflow.com/questions/19147/what-is-the-correct-way-to-create-a-single-instance-wpf-application – muaz Feb 29 '20 at 19:53

2 Answers2

3

You can use one of Mutex,Semaphore or lock statement.

Mutex: A synchronization primitive that can also be used for interprocess synchronization.

static Mutex mutexObj = new Mutex();
    static int x=0;

    static void Main(string[] args)
    {
        for (int i = 0; i < 5; i++)
        {
            Thread myThread = new Thread(Count);
            myThread.Name = $"Поток {i}";
            myThread.Start();
        }

        Console.ReadLine();
    }
    public static void Count()
    {
        mutexObj.WaitOne();
        x = 1;
        for (int i = 1; i < 9; i++)
        {
            Console.WriteLine($"{Thread.CurrentThread.Name}: {x}");
            x++;
            Thread.Sleep(100);
        }
        mutexObj.ReleaseMutex();
    }

Semaphore: Limits the number of threads that can access a resource or pool of resources concurrently.

class Program
    {
        static void Main(string[] args)
        {
            for (int i = 1; i < 6; i++)
            {
                Reader reader = new Reader(i);
            }

            Console.ReadLine();
        }
    }

    class Reader
    {
        // создаем семафор
        static Semaphore sem = new Semaphore(3, 3);
        Thread myThread;
        int count = 3;// счетчик чтения

        public Reader(int i)
        {
            myThread = new Thread(Read);
            myThread.Name = $"Читатель {i.ToString()}";
            myThread.Start();
        }

        public void Read()
        {
            while (count > 0)
            {
                sem.WaitOne();

                Console.WriteLine($"{Thread.CurrentThread.Name} входит в библиотеку");

                Console.WriteLine($"{Thread.CurrentThread.Name} читает");
                Thread.Sleep(1000);

                Console.WriteLine($"{Thread.CurrentThread.Name} покидает библиотеку");

                sem.Release();

                count--;
                Thread.Sleep(1000);
            }
        }
    }

lock statement: The lock statement acquires the mutual-exclusion lock for a given object, executes a statement block, and then releases the lock. While a lock is held, the thread that holds the lock can again acquire and release the lock. Any other thread is blocked from acquiring the lock and waits until the lock is released.

static int x=0;
static object locker = new object();
static void Main(string[] args)
{
    for (int i = 0; i < 5; i++)
    {
        Thread myThread = new Thread(Count);
        myThread.Name = "Поток " + i.ToString();
        myThread.Start();
    }

    Console.ReadLine();
}
public static void Count()
{
    lock (locker)
    {
        x = 1;
        for (int i = 1; i < 9; i++)
        {
            Console.WriteLine("{0}: {1}", Thread.CurrentThread.Name, x);
            x++;
            Thread.Sleep(100);
        }
    }
}
jasonvuriker
  • 255
  • 1
  • 12
1

Mutex and Distributed Lock are the things you are looking for.

A Mutex is a mutually exclusive flag. It acts as a gate keeper to a section of code allowing one thread in and blocking access to all others. This ensures that the code being controled will only be hit by a single thread at a time. Just be sure to release the mutex when you are done. :)

ref: What is a mutex?

You should use Mutex in one server with multiple instances of your application. and you should use DistributedLock when you have more than one server.

For C# and Redis distributed lock check Redlock. https://redis.io/topics/distlock

AminSojoudi
  • 1,904
  • 2
  • 18
  • 42