{"id":876,"date":"2023-03-11T10:32:44","date_gmt":"2023-03-11T03:32:44","guid":{"rendered":"https:\/\/csharptutorial.net\/?page_id=876"},"modified":"2023-03-11T11:45:20","modified_gmt":"2023-03-11T04:45:20","slug":"csharp-semaphoreslim","status":"publish","type":"page","link":"https:\/\/www.csharptutorial.net\/csharp-concurrency\/csharp-semaphoreslim\/","title":{"rendered":"C# SemaphoreSlim"},"content":{"rendered":"\n<p><strong>Summary<\/strong>: in this tutorial, you&#8217;ll learn how to use the C# <code>SemaphoreSlim<\/code> to limit the number of threads that can access a shared resource concurrently.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Introduction to the C# SemaphoreSlim class<\/h2>\n\n\n\n<p>A semaphore is a mechanism to limit the number of <a href=\"https:\/\/csharptutorial.net\/csharp-concurrency\/csharp-thread\/\">threads<\/a> that can access a shared resource simultaneously.<\/p>\n\n\n\n<p>The semaphore concept is based on a counter that specifies the number of available resources. <\/p>\n\n\n\n<p>To access the shared resource, a thread needs to request a permit from the semaphore.<\/p>\n\n\n\n<p>If the permit is available, the semaphore will decrement the counter. However, if the counter is zero, the semaphore will block until a permit becomes available.<\/p>\n\n\n\n<p>Once the thread completes processing the shared resource, it needs to release the permit back to the semaphore so that other threads can get the permit. When the thread releases the permit, the semaphore increments the counter<\/p>\n\n\n\n<p>C# has two classes that implement the semaphore concept: <code>Semaphore<\/code> and <code>SemaphoreSlim<\/code>.<\/p>\n\n\n\n<p>The <code>Semaphore<\/code> class has been available since the early version of the .NET Framework. The <code>SemaphoreSlim<\/code> is the more recent class introduced in .NET Framework <code>4.0<\/code> and .NET core. <\/p>\n\n\n\n<p>The <code><code>SemaphoreSlim<\/code><\/code> class is a lightweight implementation of the <code>Semaphore<\/code> class. The <code><code>SemaphoreSlim<\/code><\/code> is faster and more memory efficient than the <code>Semaphore<\/code> class.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How to use the SemaphoreSlim class<\/h2>\n\n\n\n<p>To use the <code>SemaphoreSlim<\/code> class, you follow these steps:<\/p>\n\n\n\n<p>First, create a <code>SemaphoreSlim<\/code> object and pass the initial number of permits to its constructor:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">SemaphoreSlim semaphore = <span class=\"hljs-keyword\">new<\/span>(<span class=\"hljs-number\">3<\/span>);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In this example, the semaphore object has an initial counter of 3. It means that up to three threads are allowed to access shared resources concurrently.<\/p>\n\n\n\n<p>Second, call the <code>WaitAsync()<\/code> method of the semaphore object to request a permit:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-keyword\">await<\/span> semaphore.WaitAsync();<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>WaitAsync()<\/code> method returns a <code>Task<\/code> object that waits for the permit to be granted.<\/p>\n\n\n\n<p>Third, call the <code>Release()<\/code> method of semaphore object to release the permit once you completed accessing the shared resource:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">semaphore.Release();<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>It&#8217;s a good practice to use the <code><a href=\"https:\/\/csharptutorial.net\/csharp-tutorial\/csharp-try-catch-finally\/\">try...finally<\/a><\/code> block to ensure that the <code>Release()<\/code> method is always called even if an exception is raised while accessing the shared resource:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-keyword\">await<\/span> semaphore.WaitAsync();\n\n<span class=\"hljs-keyword\">try<\/span>\n{\n    <span class=\"hljs-comment\">\/\/ Access the shared resource<\/span>\n}\n<span class=\"hljs-keyword\">finally<\/span>\n{\n    semaphore.Release();\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The following example demonstrates how to use the <code>SemaphoreSlim<\/code> class to allow a limited number of tasks can access the shared resource simultaneously:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-keyword\">using<\/span> <span class=\"hljs-keyword\">static<\/span> System.Console; \n\nSemaphoreSlim semaphore = <span class=\"hljs-keyword\">new<\/span>(<span class=\"hljs-number\">3<\/span>);\n<span class=\"hljs-keyword\">int<\/span> amount = <span class=\"hljs-number\">0<\/span>;\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">async<\/span> Task <span class=\"hljs-title\">AccessAsync<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">int<\/span> id<\/span>)<\/span>\n{\n    WriteLine(<span class=\"hljs-string\">$\"Task <span class=\"hljs-subst\">{id}<\/span> is waiting to access the amount.\"<\/span>);\n    <span class=\"hljs-keyword\">await<\/span> semaphore.WaitAsync();\n\n    <span class=\"hljs-keyword\">try<\/span>\n    {\n        WriteLine(<span class=\"hljs-string\">$\"Task <span class=\"hljs-subst\">{id}<\/span> is now accessing the amount.\"<\/span>);\n\n\n        <span class=\"hljs-comment\">\/\/ simulate some work<\/span>\n        <span class=\"hljs-keyword\">await<\/span> Task.Delay(TimeSpan.FromSeconds(<span class=\"hljs-number\">1<\/span>));\n        \n        <span class=\"hljs-comment\">\/\/ increase the counter<\/span>\n        Interlocked.Increment(<span class=\"hljs-keyword\">ref<\/span> amount);\n\n\n        <span class=\"hljs-comment\">\/\/ completed the work<\/span>\n        WriteLine(<span class=\"hljs-string\">$\"Task <span class=\"hljs-subst\">{id}<\/span> has completed accessing the amount <span class=\"hljs-subst\">{amount}<\/span>\"<\/span>);\n    }\n    <span class=\"hljs-keyword\">finally<\/span>\n    {\n        semaphore.Release();\n    }\n}\n\n\n<span class=\"hljs-comment\">\/\/ start 10 tasks to access the amount concurrently<\/span>\n<span class=\"hljs-keyword\">var<\/span>  tasks = <span class=\"hljs-keyword\">new<\/span> List&lt;Task&gt;();\n\n<span class=\"hljs-keyword\">for<\/span> (<span class=\"hljs-keyword\">int<\/span> i = <span class=\"hljs-number\">1<\/span>; i &lt;= <span class=\"hljs-number\">10<\/span>; i++)\n{\n    tasks.Add(AccessAsync(i));\n}\n\n<span class=\"hljs-comment\">\/\/ wait for all task to complete<\/span>\n<span class=\"hljs-keyword\">await<\/span> Task.WhenAll(tasks);\n\nWriteLine(<span class=\"hljs-string\">\"All tasks completed.\"<\/span>);\nReadLine();<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>How it works.<\/p>\n\n\n\n<p>First, create a <code>SemaphoreSlim<\/code> object that allows up to three tasks to access the shared resource at the same time:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">SemaphoreSlim semaphore = <span class=\"hljs-keyword\">new<\/span>(<span class=\"hljs-number\">3<\/span>);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Next, declare the <code>amount<\/code> variable that acts as a shared resource:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-keyword\">int<\/span> amount = <span class=\"hljs-number\">0<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Then, define an <a href=\"https:\/\/csharptutorial.net\/csharp-concurrency\/csharp-async-await\/\">asynchronous method<\/a> <code>AccessAsync<\/code> that takes an integer parameter <code>id<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">async<\/span> Task <span class=\"hljs-title\">AccessAsync<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">int<\/span> id<\/span>)<\/span>\n{\n    WriteLine(<span class=\"hljs-string\">$\"Task <span class=\"hljs-subst\">{id}<\/span> is waiting to access the amount.\"<\/span>);\n    <span class=\"hljs-keyword\">await<\/span> semaphore.WaitAsync();\n\n    <span class=\"hljs-keyword\">try<\/span>\n    {\n        WriteLine(<span class=\"hljs-string\">$\"Task <span class=\"hljs-subst\">{id}<\/span> is now accessing the amount.\"<\/span>);\n\n\n        <span class=\"hljs-comment\">\/\/ simulate some work<\/span>\n        <span class=\"hljs-keyword\">await<\/span> Task.Delay(TimeSpan.FromSeconds(<span class=\"hljs-number\">1<\/span>));\n        \n        <span class=\"hljs-comment\">\/\/ increase the counter<\/span>\n        Interlocked.Increment(<span class=\"hljs-keyword\">ref<\/span> amount);\n\n\n        <span class=\"hljs-comment\">\/\/ completed the work<\/span>\n        WriteLine(<span class=\"hljs-string\">$\"Task <span class=\"hljs-subst\">{id}<\/span> has completed accessing the amount <span class=\"hljs-subst\">{amount}<\/span>\"<\/span>);\n    }\n    <span class=\"hljs-keyword\">finally<\/span>\n    {\n        semaphore.Release();\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>AccessAsync()<\/code> method simulates accessing the shared variable <code>amount<\/code> using the semaphore object.<\/p>\n\n\n\n<p>The <code>AccessAsync()<\/code> method call <code>WaitAsync()<\/code> of the semaphore object to wait for a permit available, increments the <code>amount<\/code> variable using the <code>Increment()<\/code> method of the <code><a href=\"https:\/\/csharptutorial.net\/csharp-concurrency\/c-interlocked\/\">Interlocked<\/a><\/code> class, and returns the permit back to the semaphore using the <code>Release()<\/code> method of the semaphore object. <\/p>\n\n\n\n<p>The <code>AccessAsync()<\/code> method also writes some messages to the console to indicate the start and end of the task.<\/p>\n\n\n\n<p>After that, create ten tasks that execute the <code>AccessAsync<\/code> method and wait for them to complete using the <code><code>Task.WhenAll<\/code>()<\/code> method:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-comment\">\/\/ start 10 tasks to access the amount concurrently<\/span>\n<span class=\"hljs-keyword\">var<\/span>  tasks = <span class=\"hljs-keyword\">new<\/span> List&lt;Task&gt;();\n\n<span class=\"hljs-keyword\">for<\/span> (<span class=\"hljs-keyword\">int<\/span> i = <span class=\"hljs-number\">1<\/span>; i &lt;= <span class=\"hljs-number\">10<\/span>; i++)\n{\n    tasks.Add(AccessAsync(i));\n}\n\n<span class=\"hljs-comment\">\/\/ wait for all task to complete<\/span>\n<span class=\"hljs-keyword\">await<\/span> Task.WhenAll(tasks);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Finally, write a message to the console to notify the completion of all the tasks and wait for the user to press a key before terminating the program:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">WriteLine(<span class=\"hljs-string\">\"All tasks completed.\"<\/span>);\nReadLine();<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The following shows the output of the program:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">Task <span class=\"hljs-number\">1<\/span> <span class=\"hljs-keyword\">is<\/span> waiting to access the amount.\nTask <span class=\"hljs-number\">1<\/span> <span class=\"hljs-keyword\">is<\/span> now accessing the amount.\nTask <span class=\"hljs-number\">2<\/span> <span class=\"hljs-keyword\">is<\/span> waiting to access the amount.\nTask <span class=\"hljs-number\">2<\/span> <span class=\"hljs-keyword\">is<\/span> now accessing the amount.\nTask <span class=\"hljs-number\">3<\/span> <span class=\"hljs-keyword\">is<\/span> waiting to access the amount.\nTask <span class=\"hljs-number\">3<\/span> <span class=\"hljs-keyword\">is<\/span> now accessing the amount.\nTask <span class=\"hljs-number\">4<\/span> <span class=\"hljs-keyword\">is<\/span> waiting to access the amount.\nTask <span class=\"hljs-number\">5<\/span> <span class=\"hljs-keyword\">is<\/span> waiting to access the amount.\nTask <span class=\"hljs-number\">6<\/span> <span class=\"hljs-keyword\">is<\/span> waiting to access the amount.\nTask <span class=\"hljs-number\">7<\/span> <span class=\"hljs-keyword\">is<\/span> waiting to access the amount.\nTask <span class=\"hljs-number\">8<\/span> <span class=\"hljs-keyword\">is<\/span> waiting to access the amount.\nTask <span class=\"hljs-number\">9<\/span> <span class=\"hljs-keyword\">is<\/span> waiting to access the amount.\nTask <span class=\"hljs-number\">10<\/span> <span class=\"hljs-keyword\">is<\/span> waiting to access the amount.\nTask <span class=\"hljs-number\">1<\/span> has completed accessing the amount <span class=\"hljs-number\">1<\/span>\nTask <span class=\"hljs-number\">3<\/span> has completed accessing the amount <span class=\"hljs-number\">2<\/span>\nTask <span class=\"hljs-number\">5<\/span> <span class=\"hljs-keyword\">is<\/span> now accessing the amount.\nTask <span class=\"hljs-number\">4<\/span> <span class=\"hljs-keyword\">is<\/span> now accessing the amount.\nTask <span class=\"hljs-number\">2<\/span> has completed accessing the amount <span class=\"hljs-number\">3<\/span>\nTask <span class=\"hljs-number\">6<\/span> <span class=\"hljs-keyword\">is<\/span> now accessing the amount.\nTask <span class=\"hljs-number\">5<\/span> has completed accessing the amount <span class=\"hljs-number\">6<\/span>\nTask <span class=\"hljs-number\">6<\/span> has completed accessing the amount <span class=\"hljs-number\">6<\/span>\nTask <span class=\"hljs-number\">8<\/span> <span class=\"hljs-keyword\">is<\/span> now accessing the amount.\nTask <span class=\"hljs-number\">7<\/span> <span class=\"hljs-keyword\">is<\/span> now accessing the amount.\nTask <span class=\"hljs-number\">4<\/span> has completed accessing the amount <span class=\"hljs-number\">6<\/span>\nTask <span class=\"hljs-number\">9<\/span> <span class=\"hljs-keyword\">is<\/span> now accessing the amount.\nTask <span class=\"hljs-number\">9<\/span> has completed accessing the amount <span class=\"hljs-number\">7<\/span>\nTask <span class=\"hljs-number\">8<\/span> has completed accessing the amount <span class=\"hljs-number\">8<\/span>\nTask <span class=\"hljs-number\">7<\/span> has completed accessing the amount <span class=\"hljs-number\">9<\/span>\nTask <span class=\"hljs-number\">10<\/span> <span class=\"hljs-keyword\">is<\/span> now accessing the amount.\nTask <span class=\"hljs-number\">10<\/span> has completed accessing the amount <span class=\"hljs-number\">10<\/span>\nAll tasks completed.<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The output shows that:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Only three tasks can access the shared variable amount concurrently.<\/li>\n\n\n\n<li>Once a permit is available, the next task can access the shared variable.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">A practical example of the SemaphoreSlim class<\/h2>\n\n\n\n<p>The following program downloads files asynchronously using <code>SemaphoreSlim<\/code> and <code>HttpClient<\/code> classes:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-keyword\">using<\/span> <span class=\"hljs-keyword\">static<\/span> System.Console;\r\n\r\n\r\n<span class=\"hljs-keyword\">var<\/span> client = <span class=\"hljs-keyword\">new<\/span> HttpClient();\r\n<span class=\"hljs-keyword\">var<\/span> semaphore = <span class=\"hljs-keyword\">new<\/span> SemaphoreSlim(<span class=\"hljs-number\">3<\/span>);\r\n\r\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">async<\/span> Task <span class=\"hljs-title\">DownloadFileAsync<\/span>(<span class=\"hljs-params\"><span class=\"hljs-keyword\">string<\/span> url<\/span>)<\/span>\r\n{\r\n    <span class=\"hljs-keyword\">await<\/span> semaphore.WaitAsync();\r\n\r\n    <span class=\"hljs-keyword\">try<\/span>\r\n    {\r\n        WriteLine(<span class=\"hljs-string\">$\"Downloading file <span class=\"hljs-subst\">{url}<\/span>...\"<\/span>);\r\n\r\n        <span class=\"hljs-keyword\">var<\/span> response = <span class=\"hljs-keyword\">await<\/span> client.GetAsync(url);\r\n\r\n        response.EnsureSuccessStatusCode();\r\n\r\n        <span class=\"hljs-keyword\">using<\/span> (<span class=\"hljs-keyword\">var<\/span> stream = <span class=\"hljs-keyword\">await<\/span> response.Content.ReadAsStreamAsync())\r\n        <span class=\"hljs-keyword\">using<\/span> (<span class=\"hljs-keyword\">var<\/span> fileStream = File.Create(Path.GetFileName(url)))\r\n        {\r\n            <span class=\"hljs-keyword\">await<\/span> stream.CopyToAsync(fileStream);\r\n        }\r\n\r\n        WriteLine(<span class=\"hljs-string\">$\"Completed Downloading file <span class=\"hljs-subst\">{url}<\/span>.\"<\/span>);\r\n    }\r\n    <span class=\"hljs-keyword\">finally<\/span>\r\n    {\r\n        semaphore.Release();\r\n    }\r\n}\r\n\r\n<span class=\"hljs-keyword\">var<\/span> urls = <span class=\"hljs-keyword\">new<\/span> List&lt;<span class=\"hljs-keyword\">string<\/span>&gt;\r\n{\r\n    <span class=\"hljs-string\">\"https:\/\/www.ietf.org\/rfc\/rfc791.txt\"<\/span>,\r\n    <span class=\"hljs-string\">\"https:\/\/www.ietf.org\/rfc\/rfc792.txt\"<\/span>,\r\n    <span class=\"hljs-string\">\"https:\/\/www.ietf.org\/rfc\/rfc793.txt\"<\/span>,\r\n    <span class=\"hljs-string\">\"https:\/\/www.ietf.org\/rfc\/rfc794.txt\"<\/span>,\r\n    <span class=\"hljs-string\">\"https:\/\/www.ietf.org\/rfc\/rfc795.txt\"<\/span>,\r\n    <span class=\"hljs-string\">\"https:\/\/www.ietf.org\/rfc\/rfc796.txt\"<\/span>,\r\n    <span class=\"hljs-string\">\"https:\/\/www.ietf.org\/rfc\/rfc797.txt\"<\/span>,\r\n    <span class=\"hljs-string\">\"https:\/\/www.ietf.org\/rfc\/rfc798.txt\"<\/span>,\r\n    <span class=\"hljs-string\">\"https:\/\/www.ietf.org\/rfc\/rfc799.txt\"<\/span>,\r\n    <span class=\"hljs-string\">\"https:\/\/www.ietf.org\/rfc\/rfc800.txt\"<\/span>,\r\n};\r\n\r\n<span class=\"hljs-keyword\">var<\/span> tasks = <span class=\"hljs-keyword\">new<\/span> List&lt;Task&gt;();\r\n\r\n<span class=\"hljs-keyword\">foreach<\/span> (<span class=\"hljs-keyword\">var<\/span> url <span class=\"hljs-keyword\">in<\/span> urls)\r\n{\r\n    tasks.Add(DownloadFileAsync(url));\r\n}\r\n\r\n<span class=\"hljs-keyword\">await<\/span> Task.WhenAll(tasks);\r\n\r\nWriteLine(<span class=\"hljs-string\">\"Completed downloading all files.\"<\/span>);\r\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>How it works.<\/p>\n\n\n\n<p>First, create a new instance of the <code>HttpClient<\/code> class that makes HTTP requests:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-keyword\">var<\/span> client = <span class=\"hljs-keyword\">new<\/span> HttpClient();\r<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Second, create a new <code>SemaphoreSlim<\/code> object that limits the number of concurrent download to three:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-keyword\">var<\/span> semaphore = <span class=\"hljs-keyword\">new<\/span> SemaphoreSlim(<span class=\"hljs-number\">3<\/span>);\r<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Third, define the <code>DownloadFileAsync()<\/code> method that takes a URL as a parameter. The method waits on the semaphore using the <code>WaitAsync()<\/code> method, use the <code>HttpClient<\/code> object to download the file specified by the URL, and save the file into the file system. Also, the method releases the semaphore using the <code>Release()<\/code> method:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">async<\/span> Task DownloadFileAsync(string url)\r\n{\r\n    <span class=\"hljs-keyword\">await<\/span> semaphore.WaitAsync();\r\n\r\n    <span class=\"hljs-keyword\">try<\/span>\r\n    {\r\n        WriteLine($<span class=\"hljs-string\">\"Downloading file {url}...\"<\/span>);\r\n\r\n        <span class=\"hljs-keyword\">var<\/span> response = <span class=\"hljs-keyword\">await<\/span> client.GetAsync(url);\r\n\r\n        response.EnsureSuccessStatusCode();\r\n\r\n        using (<span class=\"hljs-keyword\">var<\/span> stream = <span class=\"hljs-keyword\">await<\/span> response.Content.ReadAsStreamAsync())\r\n        using (<span class=\"hljs-keyword\">var<\/span> fileStream = File.Create(Path.GetFileName(url)))\r\n        {\r\n            <span class=\"hljs-keyword\">await<\/span> stream.CopyToAsync(fileStream);\r\n        }\r\n\r\n        WriteLine($<span class=\"hljs-string\">\"Completed Downloading file {url}.\"<\/span>);\r\n    }\r\n    <span class=\"hljs-keyword\">finally<\/span>\r\n    {\r\n        semaphore.Release();\r\n    }\r\n}\r<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Fourth, define a list of URLs of the files to download:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-keyword\">var<\/span> urls = <span class=\"hljs-keyword\">new<\/span> List&lt;<span class=\"hljs-keyword\">string<\/span>&gt;\r\n{\r\n    <span class=\"hljs-string\">\"https:\/\/www.ietf.org\/rfc\/rfc791.txt\"<\/span>,\r\n    <span class=\"hljs-string\">\"https:\/\/www.ietf.org\/rfc\/rfc792.txt\"<\/span>,\r\n    <span class=\"hljs-string\">\"https:\/\/www.ietf.org\/rfc\/rfc793.txt\"<\/span>,\r\n    <span class=\"hljs-string\">\"https:\/\/www.ietf.org\/rfc\/rfc794.txt\"<\/span>,\r\n    <span class=\"hljs-string\">\"https:\/\/www.ietf.org\/rfc\/rfc795.txt\"<\/span>,\r\n    <span class=\"hljs-string\">\"https:\/\/www.ietf.org\/rfc\/rfc796.txt\"<\/span>,\r\n    <span class=\"hljs-string\">\"https:\/\/www.ietf.org\/rfc\/rfc797.txt\"<\/span>,\r\n    <span class=\"hljs-string\">\"https:\/\/www.ietf.org\/rfc\/rfc798.txt\"<\/span>,\r\n    <span class=\"hljs-string\">\"https:\/\/www.ietf.org\/rfc\/rfc799.txt\"<\/span>,\r\n    <span class=\"hljs-string\">\"https:\/\/www.ietf.org\/rfc\/rfc800.txt\"<\/span>,\r\n};<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Fifth, create a list of tasks that execute the <code>DownloadFileAsync()<\/code> concurrently and wait for all the tasks to complete using the <code><a href=\"https:\/\/csharptutorial.net\/csharp-concurrency\/csharp-whenall\/\">Task.WhenAll()<\/a><\/code> method:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\"><span class=\"hljs-keyword\">var<\/span> tasks = <span class=\"hljs-keyword\">new<\/span> List&lt;Task&gt;();\r\n\r\n<span class=\"hljs-keyword\">foreach<\/span> (<span class=\"hljs-keyword\">var<\/span> url <span class=\"hljs-keyword\">in<\/span> urls)\r\n{\r\n    tasks.Add(DownloadFileAsync(url));\r\n}\r\n\r\n<span class=\"hljs-keyword\">await<\/span> Task.WhenAll(tasks);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Finally, output a message to the console to notify that process of downloading completes:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"C#\" data-shcb-language-slug=\"cs\"><span><code class=\"hljs language-cs\">WriteLine(<span class=\"hljs-string\">\"Completed downloading all files.\"<\/span>);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">C#<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">cs<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The output shows that there are up to threads that download the files concurrently:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">Downloading file https:\/\/www.ietf.org\/rfc\/rfc791.txt...\nDownloading file https:\/\/www.ietf.org\/rfc\/rfc792.txt...\nDownloading file https:\/\/www.ietf.org\/rfc\/rfc793.txt...\nCompleted Downloading file https:\/\/www.ietf.org\/rfc\/rfc793.txt.\nDownloading file https:\/\/www.ietf.org\/rfc\/rfc794.txt...\nCompleted Downloading file https:\/\/www.ietf.org\/rfc\/rfc794.txt.\nDownloading file https:\/\/www.ietf.org\/rfc\/rfc795.txt...\nCompleted Downloading file https:\/\/www.ietf.org\/rfc\/rfc792.txt.\nDownloading file https:\/\/www.ietf.org\/rfc\/rfc796.txt...\nCompleted Downloading file https:\/\/www.ietf.org\/rfc\/rfc791.txt.\nDownloading file https:\/\/www.ietf.org\/rfc\/rfc797.txt...\nCompleted Downloading file https:\/\/www.ietf.org\/rfc\/rfc795.txt.\nDownloading file https:\/\/www.ietf.org\/rfc\/rfc798.txt...\nCompleted Downloading file https:\/\/www.ietf.org\/rfc\/rfc796.txt.\nDownloading file https:\/\/www.ietf.org\/rfc\/rfc799.txt...\nCompleted Downloading file https:\/\/www.ietf.org\/rfc\/rfc797.txt.\nDownloading file https:\/\/www.ietf.org\/rfc\/rfc800.txt...\nCompleted Downloading file https:\/\/www.ietf.org\/rfc\/rfc799.txt.\nCompleted Downloading file https:\/\/www.ietf.org\/rfc\/rfc800.txt.\nCompleted Downloading file https:\/\/www.ietf.org\/rfc\/rfc798.txt.\nCompleted downloading all files.<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Semaphore limits the number of threads that can access shared resources concurrently.<\/li>\n\n\n\n<li>Use the C# <code>SemaphoreSlim<\/code> class to implement the semaphore pattern.<\/li>\n<\/ul>\n<div class=\"helpful-block-content\" data-title=\"\">\n\t<header>\n\t\t<div class=\"wth-question\">Was this tutorial helpful ?<\/div>\n\t\t<div class=\"wth-thumbs\">\n\t\t\t<button\n\t\t\t\tdata-post=\"876\"\n\t\t\t\tdata-post-url=\"https:\/\/www.csharptutorial.net\/csharp-concurrency\/csharp-semaphoreslim\/\"\n\t\t\t\tdata-post-title=\"C# SemaphoreSlim\"\n\t\t\t\tdata-response=\"1\"\n\t\t\t\tclass=\"wth-btn-rounded wth-yes-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t\tclass=\"feather feather-thumbs-up block w-full h-full\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> Yes <\/span>\n\t\t\t<\/button>\n\n\t\t\t<button\n\t\t\t\tdata-response=\"0\"\n\t\t\t\tdata-post=\"876\"\n\t\t\t\tdata-post-url=\"https:\/\/www.csharptutorial.net\/csharp-concurrency\/csharp-semaphoreslim\/\"\n\t\t\t\tdata-post-title=\"C# SemaphoreSlim\"\n\t\t\t\tclass=\"wth-btn-rounded wth-no-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> No <\/span>\n\t\t\t<\/button>\n\t\t<\/div>\n\t<\/header>\n\n\t<div class=\"wth-form hidden\">\n\t\t<div class=\"wth-form-wrapper\">\n\t\t\t<div class=\"wth-title\"><\/div>\n\t\t\t\n\t\t\t<textarea class=\"wth-message\"><\/textarea>\n\n\t\t\t<button class=\"btn btn-primary wth-btn-submit\">Send<\/button>\n\t\t\t<button class=\"btn wth-btn-cancel\">Cancel<\/button>\n\t\t\n\t\t<\/div>\n\t<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Summary: in this tutorial, you&#8217;ll learn how to use the C# SemaphoreSlim to limit the number of threads that can access a shared resource concurrently. Introduction to the C# SemaphoreSlim class A semaphore is a mechanism to limit the number of threads that can access a shared resource simultaneously. The semaphore concept is based on [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":760,"menu_order":14,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-876","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.csharptutorial.net\/wp-json\/wp\/v2\/pages\/876","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.csharptutorial.net\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.csharptutorial.net\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.csharptutorial.net\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.csharptutorial.net\/wp-json\/wp\/v2\/comments?post=876"}],"version-history":[{"count":4,"href":"https:\/\/www.csharptutorial.net\/wp-json\/wp\/v2\/pages\/876\/revisions"}],"predecessor-version":[{"id":881,"href":"https:\/\/www.csharptutorial.net\/wp-json\/wp\/v2\/pages\/876\/revisions\/881"}],"up":[{"embeddable":true,"href":"https:\/\/www.csharptutorial.net\/wp-json\/wp\/v2\/pages\/760"}],"wp:attachment":[{"href":"https:\/\/www.csharptutorial.net\/wp-json\/wp\/v2\/media?parent=876"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}