2012-02-09 100 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; 
    } 
}