Semaphore

发布时间 2023-12-12 10:27:50作者: JohnnyLei

在WPF中,Semaphore是System.Threading命名空间中的一个类,用于控制对共享资源的访问。

如果有多个线程需要同时访问某个共享资源,可以使用Semaphore来实现线程的同步和互斥。

Semaphore通常用于以下两种场景:

  1. 控制同时访问的线程数量:可以通过Semaphore的构造函数来指定初始的可用资源数量和最大资源数量。线程可以通过调用Semaphore的WaitOne方法来申请获取资源,如果资源被占用,则线程将等待。当线程释放资源后,Semaphore将通知等待的线程继续执行。

  2. 信号量控制流:Semaphore还可以用于控制流的顺序。通过设置Semaphore的初始资源数量为0,可以阻止某些线程继续执行,直到其他线程发送信号通知。

使用Semaphore通常需要在关键代码段前后获取和释放资源。可以通过调用WaitOne方法来获取Semaphore资源,并通过调用Release方法来释放Semaphore资源。

下面是一个示例,演示了如何在WPF中使用Semaphore: 

 
using System.Threading;
using System.Windows;

public partial class MainWindow : Window
{
    private Semaphore semaphore = new Semaphore(1, 1);

    public MainWindow()
    {
        InitializeComponent();
    }

    private void AccessSharedResource()
    {
        // 获取Semaphore资源
        semaphore.WaitOne();

        // 访问共享资源
        // ...

        // 释放Semaphore资源
        semaphore.Release();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        // 在后台线程中访问共享资源
        Thread t = new Thread(new ThreadStart(AccessSharedResource));
        t.Start();
    }
}

在上述示例中,当按钮被点击时,将创建一个后台线程来访问共享资源。在AccessSharedResource方法中,首先通过调用semaphore.WaitOne方法获取Semaphore资源。然后进行共享资源的访问,使用完资源后,通过调用semaphore.Release方法释放Semaphore资源。

 

 

Semaphore 
using System;
using System.Threading;

namespace ConsoleApp2
{
    internal class Program
    {   // A semaphore that simulates a limited resource pool.
        //
        private static Semaphore _pool;

        // A padding interval to make the output more orderly.
        private static int _padding;

        private static void Main(string[] args)
        {
            // Create a semaphore that can satisfy up to three
            // concurrent requests. Use an initial count of zero,
            // so that the entire semaphore count is initially
            // owned by the main program thread.
            //
            _pool = new Semaphore(initialCount: 0, maximumCount: 3);

            // Create and start five numbered threads.
            //
            for (int i = 1; i <= 5; i++)
            {
                Thread t = new Thread(new ParameterizedThreadStart(Worker));

                // Start the thread, passing the number.
                //
                t.Start(i);
            }

            // Wait for half a second, to allow all the
            // threads to start and to block on the semaphore.
            //
            Thread.Sleep(500);

            // The main thread starts out holding the entire
            // semaphore count. Calling Release(3) brings the
            // semaphore count back to its maximum value, and
            // allows the waiting threads to enter the semaphore,
            // up to three at a time.
            //
            Console.WriteLine("Main thread calls Release(3).");
            //返回之前的计数
            _pool.Release(releaseCount: 3);

            Console.WriteLine("Main thread exits.");

            //Thread 1 begins and waits for the semaphore.
            //Thread 2 begins and waits for the semaphore.
            //Thread 3 begins and waits for the semaphore.
            //Thread 4 begins and waits for the semaphore.
            //Thread 5 begins and waits for the semaphore.
            //Main thread calls Release(3).
            //Main thread exits.
            //Thread 2 enters the semaphore.
            //Thread 1 enters the semaphore.
            //Thread 3 enters the semaphore.

            //Thread 2 releases the semaphore. //releases
            //Thread 4 enters the semaphore.
            //Thread 2 previous semaphore count: 0
            //Thread 1 releases the semaphore. //releases
            //Thread 1 previous semaphore count: 0
            //Thread 5 enters the semaphore.
            //Thread 3 releases the semaphore. //releases
            //Thread 3 previous semaphore count: 0
            //Thread 4 releases the semaphore.  //releases
            //Thread 4 previous semaphore count: 1
            //Thread 5 releases the semaphore.  //releases
            //Thread 5 previous semaphore count: 2
        }

        private static void Worker(object? num)
        {
            // Each worker thread begins by requesting the
            // semaphore.
            Console.WriteLine("Thread {0} begins " +
                "and waits for the semaphore.", num);
            _pool.WaitOne();
            //bool wok= _pool.WaitOne(200);

            // A padding interval to make the output more orderly.
            int padding = Interlocked.Add(ref _padding, 100);

            Console.WriteLine("Thread {0} enters the semaphore.", num);

            // The thread's "work" consists of sleeping for
            // about a second. Each thread "works" a little
            // longer, just to make the output more orderly.
            //
            Thread.Sleep(1000 + padding);

            Console.WriteLine("Thread {0} releases the semaphore.", num);
            int prewcount = _pool.Release();
            Console.WriteLine("Thread {0} previous semaphore count: {1}",
                num, prewcount);
        }
    }
}

 

 

简单使用

在WPF中使用Semaphore的步骤如下:

  1. 引入命名空间 首先,在你的WPF代码文件中引入System.Threading命名空间,因为Semaphore位于这个命名空间下。你可以在文件的顶部添加这个引用语句:
 
using System.Threading;
  1. 创建Semaphore实例 在你的WPF类中,创建一个Semaphore实例。你可以在类的成员变量中声明Semaphore对象:
 
private Semaphore semaphore = new Semaphore(1, 1);

上述代码创建了一个初始容量为1,最大容量为1的Semaphore对象。这表示只有一个线程可以同时访问关键部分。

  1. 在关键地方获取和释放Semaphore 在你需要保护的重要代码段前后使用semaphore的WaitOne()和Release()方法进行获取和释放。
  • 调用WaitOne()方法来获取Semaphore资源。这个方法会阻塞当前线程,直到资源可用。在获取资源之前,这个方法将等待或阻塞线程。
 
semaphore.WaitOne();
  • 调用Release()方法来释放Semaphore资源。这个方法会通知Semaphore,资源已经不再被使用,可以让其他等待的线程继续执行。
 
semaphore.Release();

以下是一个简单的示例,演示了如何在WPF中使用Semaphore:

 
using System.Threading;
using System.Windows;

public partial class MainWindow : Window
{
    private Semaphore semaphore = new Semaphore(1, 1);

    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        // 获取Semaphore资源
        semaphore.WaitOne();

        // 临界区代码
        // 在这里执行需要保护的代码

        // 释放Semaphore资源
        semaphore.Release();
    }
}

在上述示例中,当按钮被点击时,点击事件处理程序会获取Semaphore资源,然后执行临界区代码。当临界区代码执行完成后,会释放Semaphore资源,以便其他等待的线程可以获取资源并执行