在自定义管道中处置Streams / XmlReaders

时间:2014-06-23 14:20:48

标签: c# biztalk aspose.words

我在BizTalk中创建一个自定义接收管道,它将接收包含word文档作为base64字符串的消息。这会将字符串从管道配置中设置的节点提取到memoryStream中,并将其传递给Apose.Words,将其转换为PDF并将其保存到文件中。

从邮件中删除base64字符串,然后将更新的邮件分配回邮件正文。然后在消息中提升新创建的文件的路径。

我的问题是运行此管道的主机内存不断增加,并且似乎没有释放任何资源。目前它的运行速度为250MB并且没有下降。这会导致问题,因为后续电话不能及时处理。

我的代码

管道组件:

public Microsoft.BizTalk.Message.Interop.IBaseMessage Execute(IPipelineContext pContext, Microsoft.BizTalk.Message.Interop.IBaseMessage pInMsg)
    {
        string fileName = GenerateFileName();

        XmlTextReader reader = new XmlTextReader(pInMsg.BodyPart.GetOriginalDataStream());
        var removeNodeReader = new StoreAndRemoveReader(reader, nodeNameOfEncodedFileContents, fileName);

        XmlTranslatorStream translatorStream = new XmlTranslatorStream(removeNodeReader);

        pInMsg.Context.Write(contextKeyForDocumentFilePath, contextNSForDocumentFilePath, fileName);

        pInMsg.BodyPart.Data = translatorStream;

        return pInMsg;          
    }

StoreAndRemoveReader: (这取自http://biztalkmessages.vansplunteren.net/articles/dealing-with-base64/

public class StoreAndRemoveReader : XmlReader
{
    private bool inAttribute;
    private XmlReader wrappedReader;
    private string nodeNameOfEncodedFileContents;
    private string documentFilePath;

    public StoreAndRemoveReader(XmlReader wrappedReader,
                                    string nodeNameOfEncodedFileContents,
                                    string documentFilePath)
    {
        this.wrappedReader = wrappedReader;

        this.nodeNameOfEncodedFileContents = nodeNameOfEncodedFileContents;
        this.documentFilePath = documentFilePath;
    }

    public override bool Read()
    {
        Boolean result = wrappedReader.Read();

        if (wrappedReader.IsStartElement() && wrappedReader.LocalName == nodeNameOfEncodedFileContents)
        {
            if (wrappedReader.IsEmptyElement)
            {
                wrappedReader.Read();
            }
            else
            {
                Base64DecodeDocument(wrappedReader);
            }
        }

        return result;
    }

    private void Base64DecodeDocument(XmlReader reader)
    {
        byte[] buffer = new byte[1000];
        int readBytes = 0;

        //FileStream outputFile = new FileStream(this.documentFilePath, FileMode.CreateNew, FileAccess.Write, FileShare.Write);


        using (var outputStream = new MemoryStream(307200))
        {
           BinaryWriter bw = new BinaryWriter(outputStream);

           while ((readBytes = reader.ReadElementContentAsBase64(buffer, 0, 1000)) > 0)
           {
              bw.Write(buffer, 0, readBytes);
           }

            //File.WriteAllText(this.documentFilePath, "test");
           WordToPDFConversion.ConvertWordDocumentToPdf(outputStream, this.documentFilePath);
        }
    }

尝试修复

我已尝试在XmlTextReader和StoreAndRemoveReader上的管道组件中使用语句,但这并不起作用,因为我认为它会关闭传入消息的流。

我已经尝试过运行Aspose独立版,它确实使用了大量内存,但它确实会在之后清除它。

总结:

我可以在管道组件中处理读者,还是有更好的方法来提取数据?

2 个答案:

答案 0 :(得分:1)

250MB并不是特别大。你检查过Throttling了吗?

另外,是否有理由初始化300MB MemoryStream? MemoryStream可以自动扩展。

建议:

  1. 使用VirtualStream而不是MemoryStream来交换磁盘内存。
  2. 也许你可以使用FileStream。
  3. 如果你真的想变得聪明,可以在Stream接口中再次包装ReadElementContentAsBase64操作。但我认为你不需要那么远。

答案 1 :(得分:0)

我太过全神贯注于内存使用情况,我在尝试进行pdf转换时忽略了主机的CPU使用率。我已经添加了一个额外的BizTalk服务器来共享负载,CPU使用率从单个服务器上的95%〜变为每个服务器上的10%左右。