欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#實(shí)現(xiàn)跨進(jìn)程條件變量的示例代碼

 更新時(shí)間:2024年07月22日 10:22:56   作者:CodeOfCC  
C#提供的多進(jìn)程同步對(duì)象有互斥鎖和信號(hào)量,但是并沒(méi)有條件變量,雖然信號(hào)量條件變量一定程度可以等效,但是具體的使用還是會(huì)有區(qū)別,本文提供了一種條件變量的實(shí)現(xiàn)方法,可以用于進(jìn)程間的同步控制,需要的朋友可以參考下

前言

C#提供的多進(jìn)程同步對(duì)象有互斥鎖和信號(hào)量,但是并沒(méi)有條件變量。雖然信號(hào)量條件變量一定程度可以等效,但是具體的使用還是會(huì)有區(qū)別。比如說(shuō)消息隊(duì)列用條件變量就比信號(hào)量方便,用信號(hào)量要么缺乏靈活性,要么輔助代碼已經(jīng)和實(shí)現(xiàn)一個(gè)條件變量沒(méi)區(qū)別了。本文提供了一種條件變量的實(shí)現(xiàn)方法,可以用于進(jìn)程間的同步控制。

一、關(guān)鍵實(shí)現(xiàn)

1、用到的主要對(duì)象

下列對(duì)象都是跨進(jìn)程的

//互斥變量,
Mutex _mtx;
//等待發(fā)送信號(hào)量
Semaphore _waitSem;
//等待完成信號(hào)量
Semaphore _waitDone;
//共享內(nèi)存,用于存儲(chǔ)計(jì)數(shù)變量
MemoryMappedFile _mmf;
//共享內(nèi)存的讀寫對(duì)象
MemoryMappedViewAccessor _mmva;

2、初始化區(qū)分創(chuàng)建和打開(kāi)

利用Mutex判斷是創(chuàng)建還是打開(kāi)

bool isCreateNew;
_mtx = new Mutex(false, name, out isCreateNew);
 if(isCreateNew){
  //只能在創(chuàng)建時(shí),初始化共享變量
  }

3、變量放到共享內(nèi)存

條件變量需要的計(jì)算對(duì)象就兩個(gè)Waiting、Signals表示等待數(shù)和釋放數(shù)。

//放到共享內(nèi)存的數(shù)據(jù)
struct SharedData
{
    public int Waiting;
    public int Signals;
}
SharedData Data
{
    set
    {
        _mmva.Write(0, ref value);
    }
    get
    {
        SharedData ret;
        _mmva.Read(0, out ret);
        return ret;
    }
}

4、等待和釋放邏輯

參考了SDL2的條件變量實(shí)現(xiàn),具體略。有興趣的朋友可以自行查找源碼查看。

二、完整代碼

using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;

namespace AC
{
    /************************************************************************
    * @Project:  	AC::ConditionVariable
    * @Decription:   條件變量
    *                支持跨進(jìn)程
    * @Verision:  	v1.0.0    
    *              更新日志
    *              v1.0.0:實(shí)現(xiàn)基本功能              
    * @Author:  	Xin
    * @Create:  	2024/07/18 15:25:00
    * @LastUpdate:  2024/07/21 20:53:00
    ************************************************************************
    * Copyright @ 2025. All rights reserved.
    ************************************************************************/
    class ConditionVariable : IDisposable
    {
        /// <summary>
        /// 構(gòu)造方法
        /// </summary>
        public ConditionVariable()
        {
            bool isCreateNew;
            Initialize(null, out isCreateNew);
        }
        /// <summary>
        /// 構(gòu)造方法
        /// </summary>
        /// <param name="name">唯一名稱,系統(tǒng)級(jí)別,不同進(jìn)程創(chuàng)建相同名稱的本對(duì)象,就是同一個(gè)條件變量。</param>
        public ConditionVariable(string? name)
        {
            bool isCreateNew;
            Initialize(name, out isCreateNew);
        }
        /// <summary>
        /// 構(gòu)造方法
        /// </summary>
        /// <param name="name">唯一名稱,系統(tǒng)級(jí)別,不同進(jìn)程創(chuàng)建相同名稱的本對(duì)象,就是同一個(gè)條件變量。</param>
        /// <param name="isCreateNew">表示是否新創(chuàng)建,是則是創(chuàng)建,否則是打開(kāi)已存在的。</param>
        public ConditionVariable(string? name, out bool isCreateNew)
        {
            Initialize(name, out isCreateNew);
        }

        /// <summary>
        /// 等待
        /// </summary>
        /// <param name="outerMtx">外部鎖</param>
        public void WaitOne(Mutex outerMtx)
        {
            WaitOne(Timeout.InfiniteTimeSpan, outerMtx);
        }
        /// <summary>
        /// 等待超時(shí)
        /// </summary>
        /// <param name="timeout">超時(shí)時(shí)間</param>
        /// <param name="outerMtx">外部鎖</param>
        /// <returns>是則成功,否則超時(shí)</returns>
        public bool WaitOne(TimeSpan timeout, Mutex outerMtx)
        {
            bool isNotTimeout;
            //記錄等待數(shù)量
            _mtx.WaitOne();
            var ws = Data;
            ws.Waiting++;
            Data = ws;
            _mtx.ReleaseMutex();
            //解除外部的互斥鎖,讓其他線程可以進(jìn)入條件等待。
            outerMtx.ReleaseMutex();
            //等待信號(hào)
            isNotTimeout = _waitSem.WaitOne(timeout);
            _mtx.WaitOne();
            ws = Data;
            if (isNotTimeout && ws.Signals > 0)
            {
                //通知發(fā)送信號(hào)的線程,等待完成。
                _waitDone.Release();
                ws.Signals--;
            }
            ws.Waiting--;
            Data = ws;
            _mtx.ReleaseMutex();
            //加上外部互斥鎖,還原外部的鎖狀態(tài)。
            outerMtx.WaitOne();
            return !isNotTimeout;
        }
        /// <summary>
        /// 釋放,通知
        /// </summary>
        public void Release()
        {
            _mtx.WaitOne();
            var ws = Data;
            if (ws.Waiting > ws.Signals)
            {
                ws.Signals++;
                Data = ws;
                _waitSem.Release();
                _mtx.ReleaseMutex();
                _waitDone.WaitOne();
            }
            else
            {
                _mtx.ReleaseMutex();
            }
        }
        /// <summary>
        /// 釋放全部,廣播
        /// </summary>
        public void ReleaseAll()
        {
            _mtx.WaitOne();
            var ws = Data;
            if (ws.Waiting > ws.Signals)
            {
                int waiting = ws.Waiting - ws.Signals;
                ws.Signals = ws.Waiting;
                Data = ws;
                _waitSem.Release(waiting);
                _mtx.ReleaseMutex();
                _waitDone.WaitOne(waiting);
            }
            else
            {
                _mtx.ReleaseMutex();
            }
        }
        /// <summary>
        /// 銷毀對(duì)象,只會(huì)銷毀當(dāng)前實(shí)例,如果多個(gè)打開(kāi)同個(gè)名稱,其他對(duì)象不受影響
        /// </summary>
        public void Dispose()
        {
            _mtx.Dispose();
            _waitSem.Dispose();
            _waitDone.Dispose();
            _mmva.Dispose();
            _mmf.Dispose();
        }
        void Initialize(string? name, out bool isCreateNew)
        {
            Mutex? mtx = null;
            Semaphore? waitSem = null;
            Semaphore? waitDone = null;
            MemoryMappedFile? mmf = null;
            MemoryMappedViewAccessor? mmva = null;
            try
            {

                mtx = _mtx = new Mutex(false, name, out isCreateNew);
                _mtx.WaitOne();
                try
                {
                    waitSem = _waitSem = new Semaphore(0, int.MaxValue, name + ".cv.ws");
                    waitDone = _waitDone = new Semaphore(0, int.MaxValue, name + ".cv.wd");
                    var _shmPath = Path.Combine(_TempDirectory, name + ".cv");
                    mmf = _mmf = MemoryMappedFile.CreateFromFile(File.Open(_shmPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite), null, Marshal.SizeOf<SharedData>(), MemoryMappedFileAccess.ReadWrite, HandleInheritability.Inheritable, false);
                    mmva = _mmva = _mmf.CreateViewAccessor();
                    if (isCreateNew) Data = new SharedData() { Signals = 0, Waiting = 0 };
                }
                finally
                {
                    _mtx.ReleaseMutex();
                }
            }
            catch
            {
                mtx?.Dispose();
                waitSem?.Dispose();
                waitDone?.Dispose();
                mmf?.Dispose();
                mmva?.Dispose();
                isCreateNew = false;
                throw;
            }
        }
        Mutex _mtx;
        Semaphore _waitSem;
        Semaphore _waitDone;
        MemoryMappedFile _mmf;
        MemoryMappedViewAccessor _mmva;
        struct SharedData
        {
            public int Waiting;
            public int Signals;
        }
        SharedData Data
        {
            set
            {
                _mmva.Write(0, ref value);
            }
            get
            {
                SharedData ret;
                _mmva.Read(0, out ret);
                return ret;
            }
        }
        static string _TempDirectory = Path.GetTempPath() + "EE3E9111-8F65-4D68-AB2B-A018DD9ECF3C";
    }
}

三、使用示例

1、同步控制

using AC;
ConditionVariable cv = new ConditionVariable();
Mutex mutex = new Mutex();
string text = "";
//子線程發(fā)送消息
new Thread(() =>
{
    int n = 0;
    while (true)
    {
        mutex.WaitOne();
        text = (n++).ToString();
        //通知主線程
        cv.Release();
        mutex.ReleaseMutex();
    }

}).Start();
//主線程接收消息
while (true)
{
    mutex.WaitOne();
    //等待子消息
    cv.WaitOne(mutex);
    Console.WriteLine(text);
    mutex.ReleaseMutex();
}

2、跨進(jìn)程控制

進(jìn)程A

//不同進(jìn)程名稱相同就是同一個(gè)對(duì)象
ConditionVariable cv = new ConditionVariable("cv1");
Mutex mutex = new Mutex(false,"mx1");
//進(jìn)程A發(fā)送消息
while (true)
{
    mutex.WaitOne();
    //共享進(jìn)程讀寫略
    //通知進(jìn)程B
    cv.Release();
    mutex.ReleaseMutex();
}

進(jìn)程B

//不同進(jìn)程名稱相同就是同一個(gè)對(duì)象
ConditionVariable cv = new ConditionVariable("cv1");
Mutex mutex = new Mutex(false,"mx1");
//進(jìn)程B接收消息
while (true)
{
    mutex.WaitOne();
    //等待進(jìn)A程消息
    cv.WaitOne(mutex);
    //共享進(jìn)程讀寫略
    Console.WriteLine("收到進(jìn)程A消息");
    mutex.ReleaseMutex();
}

總結(jié)

以上就是今天要講的內(nèi)容,之所以實(shí)現(xiàn)這樣一個(gè)對(duì)象是因?yàn)椋P者在寫跨進(jìn)程隊(duì)列通信,用信號(hào)量實(shí)現(xiàn)發(fā)現(xiàn)有所局限,想要完善與重寫一個(gè)條件變量差異不大,索性直接實(shí)現(xiàn)一個(gè)條件變量,提供給隊(duì)列使用,同時(shí)還具體通用性,在其他地方也能使用??偟膩?lái)說(shuō),條件變量還是有用的,雖然需要遇到相應(yīng)的使用場(chǎng)景才能意識(shí)到它的作用。

到此這篇關(guān)于C#實(shí)現(xiàn)跨進(jìn)程條件變量的示例代碼的文章就介紹到這了,更多相關(guān)C#跨進(jìn)程條件變量?jī)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論