C # restrictions on concurrent programming concurrent access to resources using SemaphoreSlim

Source: Internet
Author: User

C # restrictions on concurrent programming concurrent access to resources using SemaphoreSlim
Summary

When multiple tasks or threads run in parallel, it is difficult to avoid concurrent access to some limited resources. You can consider using semaphores for this control (System. Threading. Semaphore) is a Semaphore object representing a Windows kernel. If the expected wait time is short, you can consider using SemaphoreSlim, which causes less overhead.

Semaphores in. NetFrameWork coordinate resource access by tracking the tasks or threads that enter and exit. The semaphore needs to know the maximum number of resources. When a task enters, the resource counter will be reduced by 1. When the counter is 0, if a task accesses the resource, it will be blocked, until a task leaves.

Example program: 10 tasks access 3 resources in parallel

using System;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Diagnostics;namespace Sample5_8_semaphoreslim{    class Program    {        private static int _TaskNum = 10;        private static Task[] _Tasks;        private const int MAX_RESOURCE = 3;        private const int RUN_LOOP = 10;        private static SemaphoreSlim m_Semaphore;        private static void Work1(int TaskID)        {            int i = 0;            var sw = Stopwatch.StartNew();            var rnd = new Random();            while (i < RUN_LOOP)            {                Thread.Sleep(rnd.Next(200, 500));                Console.WriteLine("TASK " + TaskID + " REQUESTing {");                m_Semaphore.Wait();                try                {                    Console.WriteLine("TASK " + TaskID + " WOrking  ...  ..." + i);                    sw.Restart();                    Thread.Sleep(rnd.Next(200, 500));                }                finally                {                    Console.WriteLine("TASK " + TaskID + " REQUESTing }");                    m_Semaphore.Release();                    i++;                }            }        }        static void Main(string[] args)        {            _Tasks = new Task[_TaskNum];            m_Semaphore = new SemaphoreSlim(MAX_RESOURCE);            int i = 0;            for (i = 0; i < _TaskNum; i++)            {                _Tasks[i] = Task.Factory.StartNew((num) =>                {                    var taskid = (int)num;                    Work1(taskid);                }, i);            }            var finalTask = Task.Factory.ContinueWhenAll(_Tasks, (tasks) =>            {                Task.WaitAll(_Tasks);                Console.WriteLine("==========================================================");                Console.WriteLine("All Phase is completed");                Console.WriteLine("==========================================================");            });            try            {                finalTask.Wait();            }            catch (AggregateException aex)            {                Console.WriteLine("Task failed And Canceled" + aex.ToString());            }            finally            {                m_Semaphore.Dispose();            }            Console.ReadLine();        }    }}
Timeout and Cancellation

Of course, semaphores cannot be blocked permanently. Semaphores also provide a timeout processing mechanism. The method is to input a TIMEOUT Wait time-Wait (int TIMEOUT) in the Wait function ). When the Wait return value is false, it indicates that it has timed out. If-1 is input, it indicates an indefinite wait.

Program example: note that m_Semaphore.Release (); has been commented out, and the task will wait 1 second and then time out.

using System;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Diagnostics;namespace Sample5_8_semaphoreslim{    class Program    {        private static int _TaskNum = 10;        private static Task[] _Tasks;        private const int MAX_RESOURCE = 3;        private const int RUN_LOOP = 10;        private static SemaphoreSlim m_Semaphore;        private static void Work1(int TaskID)        {            int i = 0;            var sw = Stopwatch.StartNew();            var rnd = new Random();            while (i < RUN_LOOP)            {                Thread.Sleep(rnd.Next(200, 500));                Console.WriteLine("TASK " + TaskID + " REQUESTing {");                if (!m_Semaphore.Wait(1000))                {                    Console.WriteLine("TASK " + TaskID + " TIMEOUT!!!");                    return;                }                try                {                    Console.WriteLine("TASK " + TaskID + " WOrking  ...  ..." + i);                    sw.Restart();                    Thread.Sleep(rnd.Next(2000, 5000));                }                finally                {                    Console.WriteLine("TASK " + TaskID + " REQUESTing }");                    //m_Semaphore.Release();                    i++;                }            }        }        static void Main(string[] args)        {            _Tasks = new Task[_TaskNum];            m_Semaphore = new SemaphoreSlim(MAX_RESOURCE);            int i = 0;            for (i = 0; i < _TaskNum; i++)            {                _Tasks[i] = Task.Factory.StartNew((num) =>                {                    var taskid = (int)num;                    Work1(taskid);                }, i);            }            var finalTask = Task.Factory.ContinueWhenAll(_Tasks, (tasks) =>            {                Task.WaitAll(_Tasks);                Console.WriteLine("==========================================================");                Console.WriteLine("All Phase is completed");                Console.WriteLine("==========================================================");            });            try            {                finalTask.Wait();            }            catch (AggregateException aex)            {                Console.WriteLine("Task failed And Canceled" + aex.ToString());            }            finally            {                m_Semaphore.Dispose();            }            Console.ReadLine();        }    }}
Cross-process or AppDomain Synchronization

Semaphore can be used if cross-process or AppDomain synchronization is required. Semaphore is the Windows Kernel Semaphore, so it is effective throughout the system.
Its main interfaces are Release and WaitOne, which are used in the same way as SemaphoreSlim.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.