Time of Update: 2018-12-07
當使用Serializable特性,如果類有更新(但有要求和以前序列化的類對象保持相容),可以使用OptionalField特性來標記新加的欄位。至於Serializable特性在類繼承上,問題不會很大,只要父類被標記Serializable特性,那麼子類就可以序列化父類的內容。 而對於ISerializable介面,由於序列化和還原序列化都得自己動手,那麼處理類更新和繼承問題就會稍複雜一些。 比如版本更新,我們可以在SerializationInfo中加入自己的版本資訊,在還原序列化中再根據不
Time of Update: 2018-12-07
StreamingContext類型出現在諸多序列化的方法中。ISerializable的GetObjectData和特殊的建構函式(用於還原序列化)。還有[OnDeserialized], [OnDeserializing], [OnSerialized],
Time of Update: 2018-12-07
全部版本的原始碼下載: 注意:此為微軟SkyDrive存檔,請用瀏覽器直接下載,用某些下載工具可能無法下載 版本更新歷史:2.0增加了對擴充表單樣式(GWL_EXSTYLE標誌)的更好支援支援:增加WindowStylesEx枚舉定義。 1.0簡單的GetWindowLongPtr和SetWindowLongPtr封裝。具體介紹可以參考:.NET(C#) 平台叫用:不依賴平台的GetWindowLongPtr和SetWindowLongPtr API
Time of Update: 2018-12-07
程式示範:進入程式,首先得輸入最大容量,比如輸入10: 接下來生產線產生了,最初當然只有0個項目,我們現在開始生產5個項目,在“生產數量”中輸入5,如: 然後點擊“生產”,5個項目就被生產了: 接下來我們再生產12個項目,加上之前的5個項目,此時一共會生產17個項目,但是總容量是10,所以會有7個生產項目要等待(線程阻塞): 接著再去生產10個項目,此時已經有7個生產項目在等待狀態,後續的生產項目需求會疊加: 現在的情況是:有10個項目已經被生產,還有17個項目等待被生產,下面我們消費5個項目,
Time of Update: 2018-12-07
不難,訣竅就是利用LINQ的GroupBy方法,然後依靠返回結果的IGrouping介面的Count屬性來判斷是否是重複元素。代碼://重複元素:3,4,5//不重複元素:1,8,9int[] arr = { 1, 3, 3, 3, 4, 5, 4, 5, 8, 9, 3 }; //不重複元素var unique = arr.GroupBy(i => i) .Where(g => g.Count() == 1) .Select(g =>
Time of Update: 2018-12-07
反射Emit中的TypeBuilder.DefineMethod並沒有直接提供對泛型參數的支援。整體過程也不是一個簡單的方法調用就可以解決的,具體總結如下過程:調用沒有指定參數和傳回值類型的TypeBuilder.DefineMethod重載,得到MethodBuilder。 使用MethodBuilder.DefineGenericParameters方法來定義泛型參數的類型名稱,比如T,K,V……然後最終方法就是xxx<T, K, V>。
Time of Update: 2018-12-07
假設有這麼一個簡單的ConfigurationSection類型(只有一個Id屬性):class MySection : ConfigurationSection{ [ConfigurationProperty("id")] public int Id { get { return (int)this["id"]; } set { this["id"] = value; } } } 那麼你的設定檔只能這樣寫:<configuration&
Time of Update: 2018-12-07
前面一篇文章:.NET(C#)平台叫用:DllImportAttribute.CharSet和字串封送編碼,介紹了平台叫用時封送字串和DllImportAttribute.CharSet的各種關係。事實上還有另外一種方法,因為字串本身也是指標,那麼在調用聲明時用IntPtr(而不是String類型)也可以,此時則需要我們手動對IntPtr做處理。使用的則是Marshal類的StringToHGlobal方法將託管堆中的字串轉換成一個非託管堆中的指標。注意需要用Marshal.FreeHGloba
Time of Update: 2018-12-07
當不使用SMTP的25連接埠號碼發送郵件,某些低許可權執行環境可以會拋出異常,最好還是在執行操作前進行許可權的檢查。 SMTP在.NET中對應的許可權是:SmtpPermission類型(還有聲明式的SmtpPermissionAttribute特性,他們都在System.Net.Mail命名空間下)。他的Access屬性控制許可權的內容。對應一個SmtpAccess枚舉。有3個值:None(沒有),Connect(串連預設連接埠25),ConnectToUnrestrictedPort(串連任
Time of Update: 2018-12-07
對於當前程式,Process.Exited事件並不起作用,如下代碼:static void Main(){ var pro = Process.GetCurrentProcess(); pro.EnableRaisingEvents = true; pro.Exited += new EventHandler(pro_Exited);} static void pro_Exited(object sender, EventArgs e){ throw new
Time of Update: 2018-12-07
我們知道,AppDomain.ProcessExit能監視當前進程的退出,而Process.Exited事件只能監視其他進程的退出。而且如果進程被強制結束AppDomain.ProcessExit不會發生的。綜上事實,我們可以用兩個進程互相監視另一個進程的Process.Exited事件來,然後如果一個進程被結束,另一個進程會重新開啟這個程式。 比如樣本中兩個程式,mgen_p1,和mgen_p2。一個程式結束後,另一個程式會馬上重新運行被結束的程式。當然如果兩個程式同時被結束,那麼他們會被徹底
Time of Update: 2018-12-07
HTTP請求包頭資訊中有一個Range屬性可以指定索取部分HTTP請求的檔案。在.NET中則通過HttpWebRequest.AddRange方法來定義資料的範圍。當添加了Range屬性的HTTP請求發送後,如果伺服器支援該請求,也就是說支援部分資料提取(也是我們常說到的支援斷點續傳的下載,所謂斷點續傳的下載就是用一個Range屬性來指定沒有下載到的範圍),那麼伺服器會返回Partial Content狀態值。否則會返回OK狀態值(200代碼)。注意如果伺服器支援Range但是HTTP
Time of Update: 2018-12-07
PLINQ的運行結果是無序的,也就是不保持原來集合的順序來操作(當然除了一些專門的排序操作)。原因則是線程的並發執行本來就充滿了不確定性,把原來一個任務分割成好幾個部分同時進行返回的結果會打亂原來的順序,如果要強制保留順序,肯定要浪費一些效能,PLINQ是可以這樣的,但預設不這樣。 先看一個LINQ樣本:var arr = new int[] { 1, 2, 3, 4, 5 };var res = arr.Where(i => i != 3);結果是:1, 2, 4,
Time of Update: 2018-12-07
和for/foreach中發生異常的表現一樣,Parallel迴圈中的任何異常都會使整個迴圈終止,注意由於整個迴圈是分塊同時進行的,因此整個迴圈不會立即終止(如果有一個線程進行中長時間工作的話,而且是發生在CancellationToken的ThrowIfCancellationRequested方法之後)。 代碼:try{ Parallel.For(0, 5, (i) => { throw new Exception("異常。迭代數字:" + i); })
Time of Update: 2018-12-07
首先當Break被調用後,迴圈中當前調用Break的執行後的迭代就沒有必要去執行了,由於並存執行打亂了執行順序,所以這個時候很可能某些不需要執行的迭代已經執行完了,這個沒辦法(也沒必要)去取消它,當然調用Break後沒有必要執行且沒有開始執行的迭代最終不會被執行。 上面只討論了“已經執行完”和“沒有執行的狀況”,對於正在執行的卻沒有必要執行的迭代,同樣沒辦法將他停止,此時ParallelLoopState.LowestBreakIteration(類型是long?,預設是null)則會成為最小的
Time of Update: 2018-12-07
更新:在C# 5.0後,await所產生的取消Task異常會直街拋出異常。比如下面的代碼,在C# 5.0/.NET 4.5中等效於:var src = new CancellationTokenSource();src.CancelAfter(100);try{ await Task.Factory.StartNew(() => { Thread.Sleep(1000); src.Token.ThrowIfCancellationRequested(
Time of Update: 2018-12-07
當你在一個Task執行中拋出異常,比如:Task.Factory.StartNew(() =>{ throw new Exception();});運行該方法,沒有任何異常拋出。 事實上此時Task的異常處於未覺察狀態,這個未覺察狀態的異常會在記憶體回收時終結器執行線程中被拋出。為了誘發這個異常,我們可以通過GC.Collect來強制記憶體回收從而引發終結器處理線程,此時Task的未覺察異常會被拋出。//在Task中拋出異常Task.Factory.StartNew(() =>
Time of Update: 2018-12-07
這個特性太碉堡了,很像WPF中的資料繫結,當然本質就是Visual Studio在調試時利用反射擷取對象的值。 建構函式中的屬性值(就是{}中的內容)不僅僅可以是簡單的屬性值。還可以是索引器,而且這一切可以嵌套。(DebuggerDisplay特性(DebuggerDisplayAttribute類型)在System.Diagnostics命名空間內) 來定義一個有DebuggerDisplay的類:
Time of Update: 2018-12-07
ConcurrentBag<T>對於同一個線程值的添加和刪除是非常快的,因為ConcurrentBag內部將資料按線程的標識而隔離儲存區 (Isolated Storage),所以一個線程從自己的資料中移除一個資料是非常快的,當然如果這個線程中沒有資料,那麼只能從其他線程中移除資料,此時會發生一些效能損耗從而確保安全執行緒! 比如從線程1中加入兩個資料,線上程2中加入一個資料。那麼當線程2調用TryTake時,被移除的資料肯定是線程2加入的那個資料://+ using System.
Time of Update: 2018-12-07
首先需要從內部瞭解一下枚舉(Enumeration),相信許多人已經知道了,當我們聲明一個這樣的枚舉類型:enum MyEnum{ AAA, BBB, CCC} 背後的IL是這樣的:.class private auto ansi sealed MyEnum extends [mscorlib]System.Enum{ .field public static literal valuetype Mgen.MyEnum AAA = int32(0) .field