2012-02-09 85 views
3

給定Queue<MyMessage>,其中MyMessage是某些類型消息的基類:所有消息類型具有不同的字段,因此它們將使用不同的字節數。因此,根據字節而不是隊列中存在的元素來衡量此隊列的填充級別是有意義的。 事實上,由於該隊列與連接相關聯,所以我可以更好地控制消息流,在隊列幾乎滿時減少流量。監視隊列的狀態

爲了達到這個目標,我想用一個自定義類MyQueue包裝一個簡單的Queue

public class MyQueue 
{ 
    private Queue<MyMessage> _outputQueue; 
    private Int32 _byteCapacity; 
    private Int32 _currentSize; // number of used bytes 

    public MyQueue(int byteCapacity) 
    { 
     this._outputQueue = new Queue<MyMessage>(); 
     this._byteCapacity = byteCapacity; 
     this._currentSize = 0; 
    } 

    public void Enqueue(MyMessage msg) 
    { 
     this._outputQueue.Enqueue(msg); 
     this._currentSize += Marshal.SizeOf(msg.GetType()); 
    } 

    public MyMessage Dequeue() 
    { 
     MyMessage result = this._outputQueue.Dequeue(); 
     this._currentSize -= Marshal.SizeOf(result.GetType()); 
     return result; 
    } 
} 

的問題是,這是不好的班,因爲Marshal.SizeOf拋出ArgumentException例外。

  1. 是否有可能以某種方式計算對象的大小(類的實例)?
  2. 是否有一些替代方案來監控字節方面的隊列填充水平?
  3. 是否有任何可以用這種方式管理的隊列?

UPDATE:作爲一種替代解決方案,我可以在每個消息類型添加一個方法int SizeBytes(),但這種方法似乎有點難看,儘管這也許是最有效的,因爲你不能簡單地測定被引用類型

public interface MyMessage 
{ 
    Guid Identifier 
    { 
     get; 
     set; 
    } 

    int SizeBytes(); 
} 

實現此接口的必須,除了實施SizeBytes()方法,還實現了Identifier屬性的類。

public class ExampleMessage 
{ 
    public Guid Identifier { get; set; } // so I have a field and its Identifier property 
    public String Request { get; set; } 

    public int SizeBytes() 
    { 
     return (Marshal.SizeOf(Identifier)); // return 16 
    } 
} 

sizeof運營商無法與Guid使用,因爲它沒有一個預定義的大小,所以我用Marshal.SizeOf()。但在這一點也許應使用實驗值:例如,由於用於GuidMarshal.SizeOf()返回16並且由於string由N char,則SizeBytes()方法可以是如下:

public int SizeBytes() 
{ 
    return (16 + Request.Length * sizeof(char)); 
} 
+2

您無法輕鬆測量參考類型。 – SLaks 2012-02-09 19:15:10

+0

如果使用Marshal.SizeOf(msg)而不是msg.GetType(),會發生什麼? – Joe 2012-02-09 19:15:11

+0

@Joe:它拋出一個'ArgumentException'。 – enzom83 2012-02-09 19:17:38

回答

6

如果您可以使用虛方法SizeOf()編輯MyMessage基類,那麼您可以讓消息類在其基元類型上使用c#sizeof運算符。 如果你可以這樣做,你的代碼的其餘部分是黃金。

+0

我認爲這是唯一有效的選擇。使用虛擬方法'SizeOf',子類必須實現它! – enzom83 2012-02-09 20:10:53

+0

是的,這是一個更多的工作,如果你使用sizeof,你可能需要在指針的幾個字節上加上指針,但它應該可以工作。讓我知道如果它! – 2012-02-09 20:37:23

+0

它的工作原理!我更新了線程。 – enzom83 2012-02-10 00:42:59

0

通過測量它們的二進制序列化的長度,您可以得到一個指示的對象大小。請注意,此數字通常會高於您的預期,因爲.NET也可能在序列化表示中包含元數據。這種方法還要求您的所有課程都標有[Serializable]屬性。

public static long GetSerializedSize(object root) 
{ 
    using (var memoryStream = new MemoryStream()) 
    { 
     var binaryFormatter = new BinaryFormatter(); 
     binaryFormatter.Serialize(memoryStream, root); 
     return memoryStream.Length; 
    } 
}