簡體   English   中英

C#用線程池的臨時結果回調客戶端應用程序的最佳方法

[英]C# The best way to callback a client application with interim results from a pool of threads

我已經編寫了一個C#庫,該庫具有一種方法來計算並行文本中多段文字的單詞。 文本的段落以字符流的形式給出,每次調用getnextchar()getnextchar()一個隨機延遲。 我的庫方法必須采用這些字符流的數組並返回組合的字頻計數。 為此,我有一個安全共享的詞頻數據結構和一個線程,用於讀取每個字符流並更新共享的集合。 當所有線程都完成后,我將數據結構返回到客戶端應用程序。

客戶端應用程序需要每10秒計算一次合並單詞的臨時結果。 為此,我使用委托每10秒回調一次客戶端,並返回結果,直到所有工作線程都已完成,然后將最終結果返回給客戶端。

我的問題是,當我用中間結果回調客戶端時,我必須鎖定共享數據結構,並等待客戶端應用程序從回調返回后才能解鎖。 在執行回調的同時,所有工作線程都被阻塞,等待數據結構上的鎖定。 這似乎並不明智,因為我不認為我應該依賴或信任客戶端代碼以立即甚至根本不返回。 但是,他們可以想到的唯一不依賴客戶端代碼的其他方法是制作數據結構的副本或快照,並將其通過回調傳遞給客戶端。 這是以犧牲內存和計算為代價的,但是一旦復制完成,工作人員就可以繼續更新共享集合,而回調函數可以做任何想要的事情。

我的問題有兩個:

1)這是兩個弊端中的較小者,這允許不良的客戶端回調實現可能阻止工作程序或定期執行昂貴的操作。

2)有沒有一種方法可以解決以上兩個問題之一?

我可以肯定地說,兩種弊端中的較大者就是信任客戶。 持有鎖時回調未知代碼是造成死鎖和更糟情況的秘訣。 是的,您將支付開銷以對結構進行快照並返回。 但是快照的額外內存超過了持有鎖時調出的風險。

我遇到過類似情況,到目前為止,快照還不是問題。 如果是這樣,您可以找到幾種方法來解決此問題。 包括增加呼叫客戶端的頻率,這將減少您必須在給定時間快照的數據量。

解決此問題的另一種方法是使用不可變數據結構。 當您准備與客戶交談時,只需中斷當前版本並將其交給客戶即可。 允許您的后台線程開始構建新線程。

最近,我在編寫庫時遇到了這樣的問題-它並不完全相同,但是基本問題是相同的-您可以信任使用該庫的客戶端多少錢。 如果可以依靠客戶端來做某件事,那么當您獲得更好的性能時該怎么辦?

我們最終要做的是有兩個代碼路徑和一個客戶端可以在我們的對象上設置的標志,以指示要采用的路徑。 從本質上講,它是一個“您可以信任我”的標志。 如果未設置(默認設置),則庫將假定它正在處理不信任的客戶端,並且永遠不會直接向客戶端提供對內部數據結構的引用-它總是有一個副本。 但是,如果客戶端設置了該標志,則他們將可以直接訪問真實結構,並且必須遵循我們設定的規則(在標志和訪問器上都有說明)。

但是,就您的情況(事件)而言,聽起來您還有另一種選擇-兩個不同的事件。 “普通”的(在將結構交給客戶之前先將其克隆),而“高級”的則持有該鎖並為其提供實際結構以供檢查。 只要確保已明確記錄在案,就可以使用高級引用,除非在事件處理程序期間,否則不能使用該引用,並且最好還是快一點,因為這樣做會延緩處理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM