亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用 SemaphoreSlim 和 Dictionary 等待 NetMQ 回復

使用 SemaphoreSlim 和 Dictionary 等待 NetMQ 回復

C#
慕沐林林 2023-09-09 16:42:03
我有兩個應用程序使用 NetMQ 相互通信。第一個應用程序內置了一個 API 控制器,第二個應用程序(引擎)在必要時與第一個應用程序來回通信。所有 API 控制器函數都是異步任務,因為我們期望同時發生許多請求。其中一個 API 控制器函數需要首先向第二個應用程序(引擎)發送 NetMQ 消息,并等待其響應,然后再將結果返回給 API 函數請求者(API 用戶)。它需要以異步方式完成所有這些,而不需要從線程池中獲取,因為正如我之前所說,我們可能有大量請求不斷地訪問此控制器。當 SemaphoreSlim 等待時,第二個應用程序(引擎)正在更新數據庫中特定記錄的狀態,并且我需要在 API 控制器函數中讀取該記錄的狀態并將其返回給 API 用戶,如果我沒有 SemaphoreSlim 等待設計,那么代碼當然會提前讀取數據庫記錄并且不會返回正確的狀態。因此,解決方案是創建等待,允許引擎更新狀態,然后通知 API 控制器函數它可以從數據庫讀取新更新的狀態。一位同事告訴我,使用 SemaphoreSlim 和 Dictionary 設置通過鎖定在函數中創建等待,并且僅在收到來自引擎的 NetMQ 回復時才從字典中釋放 SemaphoreSlim。然后代碼自然會繼續,我將檢查數據庫的更新狀態并將其返回給 API 用戶。問題在于 API 控制器函數完全忽略了 SemaphoreSlim 鎖并過早地從數據庫讀取。最有可能的是因為它是異步的,所以我的問題是,如何使 SempahoreSlim 鎖定和讀取數據庫代碼以異步方式一起工作,而不鎖定線程?我相信代碼會讓您更好地理解我正在嘗試做的事情。1. API控制器部分功能代碼://Call EngineMessenging.Queue.Enqueue(OrderPositionText + " " + UserId + " " + AssetPairId + " " + OrderType + " " + OrderRequestId + " " + rAmount + " " + rPrice + " " + Stop);//Create SemaphoreSlim Lock and add it to global Dictionary     var NewSemaphore = new SemaphoreSlim(1, 1);await NewSemaphore.WaitAsync().ConfigureAwait(false);ApiHub.UserSemaphoreDictionary.TryAdd(UserId, NewSemaphore);//Lock was released lets now read record in Database then return appropriate result to API user.                Debug.WriteLine("Checking order status for " + uuid);                OrderRequest OrderRequestRec = await _context.OrderRequest.Where(x => x.UUID == uuid).FirstOrDefaultAsync();    if (OrderRequestRec != null)                    {                        Debug.WriteLine("ORDER STATUS: " + OrderRequestRec.Status);    }2.這是另一個類中接收NetMQ消息并釋放SemaphoreSlim的代碼:                        //API Semaphore Release lock                        SemaphoreSlim checkUserId;                        if (ApiHub.UserSemaphoreDictionary.TryGetValue(UserId, out checkUserId)) {                            Debug.WriteLine("RELEASING LOCK: " + UserId);                            checkUserId.Release();                        }結果是先讀取Database,然后釋放SemaphoreSlim。我需要釋放 SemaphoreSlim,然后讀取數據庫。
查看完整描述

1 回答

?
慕婉清6462132

TA貢獻1804條經驗 獲得超2個贊

對于這個場景,我使用 aTaskCompletionSource<bool>作為一種高級事件。它具有Task可直接等待的屬性。然后,您可以從接收消息的類中調用SetResult(true)來完成任務并允許等待者繼續。

請注意,類型bool是無關緊要的:任務必須具有某種結果類型,但在這里我們只是將其用作表示事件已發生的信號方式(也就是說,我們實際上只想要 a 等待,而不是TaskTask<T>) 。

編輯以響應OP的編輯:

是的,這是完全異步的。該await關鍵字使 C# 編譯器將控制器的代碼分解為多個部分,因此后面的部分成為await可以稍后恢復的“延續”。它將延續添加到任務的完成處理程序列表中,然后放棄線程;控制器方法不再執行,因此不會耗盡線程/堆棧。

在您調用的類中SetResult,這實際上會導致任務通知(執行)處理程序,從而導致控制器的代碼喚醒并完成。無需創建額外的線程;現有的被使用,并且一旦沒有立即要做的工作就被放棄。


查看完整回答
反對 回復 2023-09-09
  • 1 回答
  • 0 關注
  • 106 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號