您可以尝试使用 a StringBuilder
(使用类似绳索实现的 4.0 版本)流式传输值。
此示例必须在Release
模式下执行并Start Without Debugging
附带 (CTRL-F5)。Debug
模式和GC都Start Debugging
太乱了。
public class SerializableWork
{
// This is very often between 100-120k bytes. This is actually a String - not just for the purposes of this example
public String WorkContext { get; set; }
// This is quite large as well but usually less than 85k bytes. This is actually a String - not just for the purposes of this example
public String ContextResult { get; set; }
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Initial memory: {0}", GC.GetTotalMemory(true));
var sw = new SerializableWork { WorkContext = new string(' ', 1000000), ContextResult = new string(' ', 1000000) };
Console.WriteLine("Memory with objects: {0}", GC.GetTotalMemory(true));
using (var mq = new MessageQueue(@".\Private$\Test1"))
{
mq.Send(sw);
}
sw = null;
Console.WriteLine("Memory after collect: {0}", GC.GetTotalMemory(true));
using (var mq = new MessageQueue(@".\Private$\Test1"))
{
StringBuilder sb1, sb2;
using (var msg = mq.Receive())
{
Console.WriteLine("Memory after receive: {0}", GC.GetTotalMemory(true));
using (var reader = XmlTextReader.Create(msg.BodyStream))
{
reader.ReadToDescendant("WorkContext");
reader.Read();
sb1 = ReadContentAsStringBuilder(reader);
reader.ReadToFollowing("ContextResult");
reader.Read();
sb2 = ReadContentAsStringBuilder(reader);
Console.WriteLine("Memory after creating sb: {0}", GC.GetTotalMemory(true));
}
}
Console.WriteLine("Memory after freeing mq: {0}", GC.GetTotalMemory(true));
GC.KeepAlive(sb1);
GC.KeepAlive(sb2);
}
Console.WriteLine("Memory after final collect: {0}", GC.GetTotalMemory(true));
}
private static StringBuilder ReadContentAsStringBuilder(XmlReader reader)
{
var sb = new StringBuilder();
char[] buffer = new char[4096];
int read;
while ((read = reader.ReadValueChunk(buffer, 0, buffer.Length)) != 0)
{
sb.Append(buffer, 0, read);
}
return sb;
}
}
我直接读取Message.BodyStream
an 中的消息,XmlReader
然后转到我需要的元素,并使用块读取数据XmlReader.ReadValueChunk
最后我无处使用string
对象。唯一的大块内存是Message
.