日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

【译】最大限度地降低多线程 C# 代码的复杂性

發布時間:2025/6/17 C# 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【译】最大限度地降低多线程 C# 代码的复杂性 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
【譯】最大限度地降低多線程 C# 代碼的復雜性 原文:【譯】最大限度地降低多線程 C# 代碼的復雜性

分支或多線程編程是編程時最難最對的事情之一。這是由于它們的并行性質所致,即要求采用與使用單線程的線性編程完全不同的思維模式。對于這個問題,恰當類比就是拋接雜耍表演者,必須在空中拋接多個球,而不要讓它們相互干擾。這是一項重大挑戰。然而,通過正確的工具和思維模式,這項挑戰是能應對的。

本文將深入介紹我為了簡化多線程編程和避免爭用條件、死鎖等其他問題而編寫的一些工具。可以說,工具鏈以語法糖和神奇委托為依據。不過,引用偉大的爵士音樂家 Miles Davis 的話:“在音樂中,沒有聲音比有聲音更重要。” 聲音間斷就產生了奇跡。

從另一個角度來說,不一定是關乎可以編碼什么,而是關乎可以選擇不編碼什么,因為你希望通過間斷代碼行產生一點奇跡。引用 Bill Gates 的一句話:“根據代碼行數來衡量工作質量就像通過重量來衡量飛機質量一樣。” 因此,我希望能幫助開發人員減少編碼量,而不是教導開發人員如何編寫更多代碼。

同步挑戰

在多線程編程方面遇到的第一個問題是,同步對共享資源的訪問權限。當兩個或多個線程共享對某個對象的訪問權限且可能同時嘗試修改此對象時,就會出現這個問題。當 C# 首次發布時,lock 語句實現了一種基本方法,可確保只有一個線程能訪問指定資源(如數據文件),且效果很好。C# 中的 lock 關鍵字很容易理解,它獨自顛覆了我們對這個問題的思考方式。

不過,簡單的 lock 存在一個主要缺陷:它不區分只讀訪問權限和寫入訪問權限。例如,可能要從共享對象中讀取 10 個不同的線程,并且通過 System.Threading 命名空間中的 ReaderWriterLockSlim 類授權這些線程同時訪問實例,而不導致問題發生。與 lock 語句不同,此類可便于指定代碼是將內容寫入對象,還是只從對象讀取內容。這樣一來,多個讀取器可以同時進入,但在其他所有讀寫線程均已完成自己的工作前,拒絕任何寫入代碼訪問。

現在的問題是:如果使用 ReaderWriterLock 類,語法就會變得很麻煩,大量的重復代碼既降低了可讀性,又隨時間變化增加了維護復雜性,并且代碼中通常會分散有多個 try 和 finally 塊。即使是簡單的拼寫錯誤,也可能會帶來日后有時極難發現的災難性影響。?

通過將 ReaderWriterLockSlim 封裝到簡單的類中,這個問題瞬間解決,不僅重復代碼不再會出現,而且還降低了小拼寫錯誤毀一天勞動成果的風險。圖 1?中的類完全基于 lambda 技巧。可以說,這就是對一些委托應用的語法糖(假設存在幾個接口)。最重要的是,它在很大程度上有助于實現避免重復代碼原則 (DRY)。

圖 1:封裝 ReaderWriterLockSlim 1 public class Synchronizer<TImpl, TIRead, TIWrite> where TImpl : TIWrite, TIRead { 2 ReaderWriterLockSlim _lock = new ReaderWriterLockSlim (); 3 TImpl _shared; 4 5 public Synchronizer (TImpl shared) { 6 _shared = shared; 7 } 8 9 public void Read (Action<TIRead> functor) { 10 _lock.EnterReadLock (); 11 try { 12 functor (_shared); 13 } finally { 14 _lock.ExitReadLock (); 15 } 16 } 17 18 public void Write (Action<TIWrite> functor) { 19 _lock.EnterWriteLock (); 20 try { 21 functor (_shared); 22 } finally { 23 _lock.ExitWriteLock (); 24 } 25 } 26 }

圖 1?中只有 27 行代碼,但卻精妙簡潔地確保對象跨多個線程進行同步。此類假定類型中有讀取接口和寫入接口。如果由于某種原因而無法更改需要將訪問權限同步到的基礎類實現,也可以重復模板類本身三次,通過這種方式使用它。基本用法如圖 2?所示。

圖 2:使用 Synchronizer 類 1 interface IReadFromShared { 2 string GetValue (); 3 } 4 5 interface IWriteToShared { 6 void SetValue (string value); 7 } 8 9 class MySharedClass : IReadFromShared, IWriteToShared { 10 string _foo; 11 12 public string GetValue () { 13 return _foo; 14 } 15 16 public void SetValue (string value) { 17 _foo = value; 18 } 19 } 20 21 void Foo (Synchronizer<MySharedClass, IReadFromShared, IWriteToShared> sync) { 22 sync.Write (x => { 23 x.SetValue ("new value"); 24 }); 25 sync.Read (x => { 26 Console.WriteLine (x.GetValue ()); 27 }) 28 }

在圖 2?的代碼中,無論有多少線程在執行 Foo 方法,只要執行另一個 Read 或 Write 方法,就不會調用 Write 方法。不過,可以同時調用多個 Read 方法,而不必在代碼中分散多個 try/catch/finally 語句,也不必不斷重復相同的代碼。我在此鄭重聲明,通過簡單字符串來使用它是沒有意義的,因為 System.String 不可變。我使用簡單的字符串對象來簡化示例。

基本思路是,必須將所有可以修改實例狀態的方法都添加到 IWriteToShared 接口中。同時,應將所有只從實例讀取內容的方法都添加到 IReadFromShared 接口中。通過將諸如此類的問題分散到兩個不同的接口,并對基礎類型實現這兩個接口,可使用 Synchronizer 類來同步對實例的訪問權限。這樣一來,將訪問權限同步到代碼的做法變得更簡單,并且基本上可以通過更具聲明性的方式這樣做。

在多線程編程方面,語法糖可能會決定成敗。調試多線程代碼通常極為困難,并且創建同步對象的單元測試可能會是徒勞無功之舉。

如果需要,可以創建只包含一個泛型參數的重載類型,不僅繼承自原始 Synchronizer 類,還將它的一個泛型參數作為類型參數三次傳遞到它的基類。這樣一來,就不需要讀取接口或寫入接口了,因為可以直接使用類型的具體實現。不過,這種方法要求手動處理需要使用 Write 或 Read 方法的部分。此外,雖然它的安全性稍差一點,但確實可便于將無法更改的類包裝到 Synchronizer 實例中。

用于分支的 lambda 集合

邁出第一步來使用神奇的 lambda(或在 C# 中稱為“委托”)后,不難想象,可以利用它們完成更多操作。例如,反復出現的常見多線程主題是,讓多個線程與其他服務器聯系,以提取數據并將數據返回給調用方。

最簡單的例子就是,應用程序從 20 個網頁讀取數據,并在完成后將 HTML 返回給一個根據所有網頁的內容創建某種聚合結果的線程。除非為每個檢索方法都創建一個線程,否則此代碼的運行速度比預期慢得多:99% 的所有執行時間可能會花在等待 HTTP 請求返回上。

在一個線程上運行此代碼的效率很低,并且線程創建語法非常容易出錯。隨著你支持多個線程及其助理對象,挑戰變得更嚴峻,開發人員不得不在編寫代碼時使用重復代碼。意識到可以創建委托集合和用于包裝這些委托的類后,便能使用一個方法調用來創建所有線程。這樣一來,創建線程就輕松多了。

圖 3?中的一段代碼創建兩個并行運行的此類 lambda。請注意,此代碼實際上來自我的第一版 Lizzie 腳本語言的單元測試 (bit.ly/2FfH5y8)。

圖 3:創建 lambda 1 public void ExecuteParallel_1 () { 2 var sync = new Synchronizer<string, string, string> ("initial_"); 3 4 var actions = new Actions (); 5 actions.Add (() => sync.Assign ((res) => res + "foo")); 6 actions.Add (() => sync.Assign ((res) => res + "bar")); 7 8 actions.ExecuteParallel (); 9 10 string result = null; 11 sync.Read (delegate (string val) { result = val; }); 12 Assert.AreEqual (true, "initial_foobar" == result || result == "initial_barfoo"); 13 }

仔細看看這段代碼便會發現,計算結果并未假定我的兩個 lambda 的執行存先后順序。執行順序并未明確指定,并且這些 lambda 是在不同的線程上執行。這是因為,使用圖 3?中的 Actions 類,可以向它添加委托,這樣稍后就能決定是要并行執行委托,還是按順序執行委托。

為此,必須使用首選機制創建并執行許多 lambda。在圖 3?中可以看到前面提到的 Synchronizer 類,用于同步對共享字符串資源的訪問權限。不過,它對 Synchronizer 使用了新方法 Assign,我并未在圖 1中的列表內為 Synchronizer 類添加此方法。Assign 方法使用前面 Write 和 Read 方法中使用的相同“lambda 技巧”。

若要研究 Actions 類的實現,請務必下載 Lizzie 版本 0.1,因為我在后面推出的版本中完全重寫了代碼,使之成為獨立編程語言。

C# 中的函數式編程

大多數開發人員往往認為,C# 幾乎與面向對象的編程 (OOP) 同義或至少密切相關,事實顯然如此。不過,通過重新思考如何使用 C#,并深入了解它的各方面功能,解決一些問題就變得更加簡單了。目前形式的 OOP 不太易于重用,原因很多是因為它是強類型。

例如,如果重用一個類,就不得不重用初始類引用的每個類(在兩種情況下,類都是通過組合和繼承進行使用)。此外,類重用還會強制重用這些第三方類引用的所有類等。如果這些類是在不同的程序集中實現,必須添加各種各樣的程序集,才能獲得對一個類型上單個方法的訪問權限。

我曾經看過一個可以說明這個問題的類比:“雖然想要的是香蕉,但最終得到的是手拿香蕉的大猩猩,以及大猩猩所居住的熱帶雨林。” 將這種情況與使用更動態的語言(如 JavaScript)進行重用做比較,后者并不關心類型,只要它實現函數本身使用的函數即可。通過略微寬松類型方法生成的代碼更靈活、更易于重用。委托可以實現這一點。

可使用 C# 來改善跨多個項目重用代碼的過程。只需要理解函數或委托也可以是對象,并且可以通過弱類型方式控制這些對象的集合。

早在 2018 年 11 月發行的《MSDN 雜志》中,我發表過一篇標題為“使用符號委托創建你自己的腳本語言”的文章 (msdn.com/magazine/mt830373)。本文中提到的有關委托的思路是在這篇文章的基礎之上形成。本文還介紹了 Lizzie,這是我的自制腳本語言,它的存在歸功于這種以委托為中心的思維模式。如果我使用 OOP 規則創建了 Lizzie,我會認為,它在大小上可能至少大一個數量級。

當然,如今 OOP 和強類型處于主導地位,想要找到一個主要必需技能不要求它的職位描述,幾乎是不可能的。我在此鄭重聲明,我創建 OOP 代碼的時間已超過 25 年,所以,我與任何人一樣都會因為對強類型有偏見而感到內疚。然而,如今我在編碼方法上更加務實,對類層次結構的最終外觀失去興趣。

并不是我不欣賞外觀精美的類層次結構,而是收益遞減。添加到層次結構中的類越多,它就變得越臃腫,直到因不堪重壓而崩潰。有時,卓越的設計只用很少的方法、更少的類和大多數松散耦合的函數,這樣就可以輕松擴展代碼,也就不需要“引入大猩猩和熱帶雨林”了。

回到本文反復出現的主題(從 Miles Davis 的音樂方法中獲得靈感):少即是多(“沒有聲音比有聲音更重要”)。 代碼也不例外。間斷代碼行往往會產生奇跡,最佳解決方案的衡量依據更多是不編碼什么,而不是編碼什么。連傻瓜也可以將喇叭吹響,但只有為數不多的人才能用喇叭吹奏出音樂。像 Miles 這樣能創造出奇跡的人就更少了。

?


原文作者:Thomas Hansen

原文地址:Minimize Complexity in Multithreaded C# Code

posted on 2019-03-24 15:09 NET未來之路 閱讀(...) 評論(...) 編輯 收藏

轉載于:https://www.cnblogs.com/lonelyxmas/p/10588287.html

總結

以上是生活随笔為你收集整理的【译】最大限度地降低多线程 C# 代码的复杂性的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲国产中文字幕在线观看 | 国产丰满大乳奶水在线视频 | 床戏高潮做进去大尺度视频网站 | 人妻少妇偷人精品视频 | 色综合天天综合网天天狠天天 | 永久免费av| 日本一区二区精品视频 | 少妇色 | 精品久久久久久久久久岛国gif | 美女久久久久久久久 | 久热在线| 521av在线| 69av视频在线 | 九一精品一区 | 深爱五月网 | 天天干,天天干 | 665566综合网| 国产又大又粗又长 | 日本成人激情视频 | 午夜不卡福利 | 成人免费网站 | 黄色1级视频 | 久久久久久香蕉 | 夜色一区二区三区 | 搡老熟女老女人一区二区 | 小箩莉末发育娇小性色xxxx | 亚洲精品123区 | 天天舔天天操天天干 | 91精品国产色综合久久不8 | 亚洲精品无码久久久 | 成人av手机在线 | 欧美日韩在线观看免费 | 中文字幕亚洲在线观看 | 精品在线视频观看 | 一区二区三区四区在线观看视频 | www性| 国产主播福利 | 国产精品视频免费网站 | 精品探花| 久久3p| 欧美视频一 | 久久久精品人妻一区二区三区四 | 欧美视频在线免费看 | 国产日韩欧美一区二区 | 超碰偷拍| 亚洲精品视频网 | 欧美一级欧美三级在线观看 | 欧美日韩在线成人 | 国产免费高清视频 | 国产男女猛烈无遮挡免费观看网站 | www 在线观看视频 | 99自拍偷拍视频 | 男生插女生视频 | 91久久久精品 | 少妇精品亚洲一区二区成人 | 一区二区三区四区在线免费观看 | 亚洲综合不卡 | 九九热视频在线免费观看 | 与子敌伦刺激对白播放的优点 | 欧美特级黄色大片 | 美女毛片网站 | 久久亚洲av午夜福利精品一区 | 美女的胸给男人玩视频 | 精品人妻一区二区三区四区久久 | 欧美爱爱一区二区 | 亚洲激情在线观看视频 | 福利视频免费 | 有码av在线 | 欧美一级在线观看视频 | 在线播放视频高清在线观看 | 国产chinasex麻豆videos | 国产91熟女高潮一区二区 | av片毛片 | 荫道bbwbbb高潮潮喷 | 在线成人免费 | 亚洲精品日产精品乱码不卡 | 成人激情四射网 | 大桥未久视频在线观看 | 特级西西人体444www高清大胆 | 午夜看毛片 | 欧美福利在线观看 | 亚洲乱码国产乱码精品精大量 | 午夜免费网 | 成人一区二区视频 | 麻豆回家视频区一区二 | 小泽玛利亚一区二区三区在线观看 | 黄在线免费 | 亚洲精品久久一区二区三区777 | 国产精品成人3p一区二区三区 | 永久免费看黄 | 日韩www| 日韩激情成人 | 九色porny视频 | 日日干日日射 | av黄色片在线观看 | 可以直接观看的av | 91看片网| 欧美一级艳片视频免费观看 | 日本免费一区视频 |