C#信号量用法简单示例

yizhihongxing

当我们需要对一个或多个资源进行控制时,可以使用信号量。信号量是一种同步原语,它可以被用来跟踪资源的可用性。在这篇文章中,我们将会讲解C#中的信号量用法,包括信号量的基本操作和信号量用法的示例。

基本用法

在C#中,信号量可以通过System.Threading命名空间的Semaphore类来实现。Semaphore类封装了Windows内核对象,可以根据需要增加或删除元素。常用的构造函数有以下两种:

  • Semaphore(int initialCount, int maximumCount):初始化一个 Semaphore 实例,它同时限制了同时访问信号量的线程数量。initialCount参数指定最初可使用的锁定数量;maximumCount指定信号量的最大值,最大值不能小于initialCount值。
  • Semaphore(int initialCount, int maximumCount, string name, out bool createdNew):初始化具有指定名称的 Semaphore 对象,如果 Semaphore 对象不存在,则新建一个。name参数指定 Semaphore 实例的名称,createdNew参数指示是否创建了 Semaphore 实例。

Semaphore类有以下一些常见的方法:

  • WaitOne():尝试减小 Semaphore 对象的可用计数器。如果当前可用的计数器为 0,则会阻止调用线程,直到 Semaphore 可用为止。
  • WaitForMultipleObjects(IntPtr[], bool, int):暂停当前线程,直到在多个等待线程句柄中的一个变为终止状态或等待线程时间到达限制。在接收到一个等待的句柄后,方法会将其他等待的句柄从等待状态下移除。
  • Release():增加 Semaphore 对象计数器的值,从而允许创建者线程使用 Semaphore。

接下来是Semaphore类的一个简单示例:

using System;
using System.Threading;

class SemaphoreDemo
{
    static Semaphore _pool = new Semaphore(0, 2);

    static void Main(string[] args)
    {
        for (int i = 1; i <= 5; i++)
        {
            Thread t = new Thread(new ParameterizedThreadStart(Worker));
            t.Start(i);
        }

        Console.ReadLine();
    }

    static void Worker(object id)
    {
        Console.WriteLine("Worker {0} 开始执行...", id);
        _pool.WaitOne();
        Console.WriteLine("Worker {0} 开始使用资源...", id);
        Thread.Sleep(5000);
        Console.WriteLine("Worker {0} 使用资源结束...", id);
        _pool.Release();
    }
}

在这个示例中,Semaphore对象的最大计数器值被设置为2,以限制最多只有两个线程可以同时访问受信号量保护的资源。五个不同的工作线程被创建并启动,它们共享两个信号量。当一个工作线程需要访问资源时,它会等待另一个线程释放一个信号量,然后才能继续执行。

示例1:控制并发访问Web API

一个常见的示例是,你的应用程序需要同步地访问一个Web API。由于API的限制,你最多只能有三个并发连接。为了管理你的连接,你可以使用一个信号量。

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;

class WebApiManager
{
    static Semaphore _semaphore;

    static WebApiManager()
    {
        _semaphore = new Semaphore(3, 3);
    }

    public static async Task<string> GetDataAsync(string url)
    {
        _semaphore.WaitOne();

        try
        {
            using (var client = new HttpClient())
            {
                var response = await client.GetStringAsync(url);
                return response;
            }
        }
        finally
        {
            _semaphore.Release();
        }
    }
}

在上面的示例中,使用了一个Semaphore对象来限制API调用的并发量。Semaphore对象的初始计数是3,因此最多只能有3个线程同时调用GetDataAsync()方法。在传入url参数之后,线程通过调用Semaphore对象的WaitOne()方法来等待可用的信号量。如果当前没有可用的信号量,线程将被阻塞,直到有一个信号量可用或者超时。当信号量可用时,线程可以继续执行,使用HttpClient发起API调用。当线程完成调用时,它调用信号量的Release()方法来释放一个信号量。

示例2:实现资源池

另一个示例是,你需要管理一个资源池,例如数据库连接、网络连接等。由于这些资源是有限的,你需要一个机制来限制资源的并发使用量。你可以使用一个信号量来实现这个功能。

class ResourcePool<T>
{
    private Stack<T> _resources;
    private Semaphore _semaphore;

    public ResourcePool(IEnumerable<T> resources, int maxCount)
    {
        _resources = new Stack<T>(resources);
        _semaphore = new Semaphore(maxCount, maxCount);
    }

    public T Acquire()
    {
        _semaphore.WaitOne();

        T resource;

        lock (_resources)
        {
            resource = _resources.Pop();
        }

        return resource;
    }

    public void Release(T resource)
    {
        lock (_resources)
        {
            _resources.Push(resource);
        }

        _semaphore.Release();
    }
}

在上面的示例中,使用一个Semaphore对象来限制ResourcePool对象中的资源并发使用量。在构造函数中,你需要指定初始资源列表和Semaphore最大计数器值。在Acquire()方法中,线程等待一个可用的信号量,并且从资源池中弹出一个可用的资源。在Release()方法中,线程将资源放回资源池,并释放一个信号量。

这样,就实现了一个Thread-Safe的资源池,可以在多线程环境下被安全地访问。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#信号量用法简单示例 - Python技术站

(0)
上一篇 2023年5月15日
下一篇 2023年5月15日

相关文章

  • C# TextWriter.Close – 关闭文本编写器

    C#中的TextWriter类是一个抽象类,用于向文本或流中写入字符。 Close() 方法是 TextWriter 类的一个实例方法,用于关闭当前 writer 对象并释放与此对象关联的所有系统资源(比如内存和句柄)。 以下是 TextWriter.Close 方法的使用方法: public virtual void Close (); 在调用 Close…

    C# 2023年4月19日
    00
  • C#实现前向最大匹、字典树(分词、检索)的示例代码

    如果要实现分词和检索功能,可以用前向最大匹配和字典树算法。在C#中实现这两个功能,可以按照以下步骤进行: 实现前向最大匹配算法 前向最大匹配算法是将待分词的文本从左到右进行扫描,每次取出最长的词作为分词结果。为了实现该算法,需要将待分词的文本和词典中的词进行转换,以便进行匹配。下面是C#中的前向最大匹配算法示例代码: public static List&l…

    C# 2023年5月31日
    00
  • ASP.NET Core按用户等级授权的方法

    以下是关于“ASP.NET Core 按用户等级授权的方法”的完整攻略: 1. ASP.NET Core 授权 ASP.NET Core 授权是一种用于限用户访问应用程序中某些资源的机制。通过授权,我们限制用户访问某些页面、API 或其他资源,以保护应用的安全性和完整性。 2. ASP.NET Core 按等级授权 ASP.NET Core 按用户等级授权是…

    C# 2023年5月12日
    00
  • asp.net下定制日期输出格式的代码

    当在ASP.NET中输出日期时,默认情况下日期格式会是 “月/日/年” 或者 “日/月/年”,这样的输出格式不一定满足实际需要,我们可以通过一些代码的方式来定制日期输出格式。 下面是具体的攻略步骤: 1. 设置Globle.asax文件 在 ASP.NET 应用程序根目录下新建 Global.asax 文件,添加以下代码: <%@ Applicatio…

    C# 2023年5月31日
    00
  • .NET异步编程总结—-四种实现模式代码总结

    “.NET异步编程总结—-四种实现模式代码总结”是一篇涉及异步编程的技术总结文章,对于需要使用异步编程进行开发的.NET开发人员来说,本文是一份非常有用的参考材料。下面将详细讲解这篇文章的内容和适用场景,同时提供两个相关示例。 一、适用场景 异步编程是一种可以提高程序性能、改善用户体验的编程模式。在系统需要进行高并发、高 I/O 的情况下,异步编程表现出…

    C# 2023年5月31日
    00
  • C# Console.WriteLine()方法: 在控制台输出一行文本

    Console.WriteLine()的作用与使用方法 Console.WriteLine() 是 C# 语言中用来将数据输出到控制台窗口并自动换行的函数。它接收一个或多个参数,参数之间可以用逗号(,)分隔。该函数将每个参数转化为字符串并将它们输出到控制台窗口,并在其后面添加一个换行符(\n)。 使用方法 调用 Console.WriteLine() 函数有…

    C# 2023年4月19日
    00
  • 基于C#制作一个休息提醒闹钟的详细步骤

    下面我将介绍基于C#制作一个休息提醒闹钟的详细步骤。 步骤一:新建WPF应用程序 从Visual Studio的开始菜单或欢迎屏幕中,选择新建项目(或点击Ctrl + Shift + N)。 选择WPF应用程序模板,并选择合适的项目名称和位置。然后点击“创建”按钮。 步骤二:设计用户界面 在设计用户界面方面,可参考以下示例: <Window x:Cla…

    C# 2023年5月15日
    00
  • C#使用Monitor类实现线程同步

    关于“C#使用Monitor类实现线程同步”的完整攻略,以下为具体内容: Monitor类简介 Monitor类属于System.Threading命名空间,它提供了一种同步机制以控制对共享资源的访问。Monitor实现相对于lock语句的优点在于使用了更低层次的同步原语,因此可以更细粒度地控制线程的同步。 Monitor类的基本用法 首先是使用Monito…

    C# 2023年5月15日
    00
合作推广
合作推广
分享本页
返回顶部