从控制台应用程序批量打印RDLC报告时处理流

时间:2013-05-13 18:12:36

标签: c# printing stream render rdlc

我正在从控制台应用程序打印报告。我开始使用微软(http://msdn.microsoft.com/en-us/library/ms252172(v=vs.100).aspx)规定的方式。在这种技术中,人们会像这样呈现一个报告:

report.Render("Image", deviceInfo, CreateStream, out warnings);

其中CreateStream是对函数的回调:

private Stream CreateStream(string name, string fileNameExtension, 
  Encoding encoding, string mimeType, bool willSeek)
{
    Stream stream = new FileStream(name + "." + fileNameExtension, 
      FileMode.Create);
    m_streams.Add(stream);
    return stream;
}

您的想法是将报表呈现为文件,将流打开并收集在数组中。然后,一旦它们全部呈现,您将遍历该数组,使用这些打开的流将文件内容发送到打印机。

这适用于一些报告,但在我的情况下,我打印大约1500页的一页报告。显然,我不能让所有这些流悬空,而不会使性能严重下降。所以,我修改了一些东西。我创建了一个我在CreateStream回调中使用的类级流对象(RenderStream),并将文件名保存在集合中。

RenderStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.Read);
RenderedFileList.Add(fileName);

然后在Report.Render()函数返回后再使用RenderStream.Dispose()。

这样我的溪流就会保持关闭和处理。完成所有导出后,当我去打印时,在PrintPage事件中我这样做:

private void PrintPage(object sender, PrintPageEventArgs ev)
{
    using (Stream stream = new FileStream(RenderedFileList[fileCounter], FileMode.Open, FileAccess.Read, FileShare.Read))
    {
        Metafile pageImage = new Metafile(stream);
        ev.Graphics.DrawImage(pageImage, ev.PageBounds);
    }
}

现在,这就是问题所在。虽然我通常打开流向这些呈现文件的流没有问题,但我在打印时尝试访问这些文件的大约5%会返回异常,报告该文件无法访问,因为它是由另一个文件打开的处理。即使先前的流已被处置。

我该怎么做才能解决这个问题?

2 个答案:

答案 0 :(得分:2)

我面临同样的问题,从另一个方面出来。我按照这种方法引用your link ..

保留一个列表以获取该流创建的所有文件:

 private List<string> _emfFiles = new List<string>();

修改后的CreateStream方法:

private Stream CreateStream(string name, string fileNameExtension, 
  Encoding encoding, string mimeType, bool willSeek)
{
    Stream stream = new FileStream(name + "." + fileNameExtension, FileMode.Create);
    m_streams.Add(stream);

    //Get all the files
    _emfFiles.Add(name + "." + fileNameExtension);

    return stream;
}

这样_emfFiles列表包含流创建的所有EMF文件。然后,在Disposed方法中;

public void Disposed()
    {
        if (m_streams != null)
        {
            foreach (Stream stream in m_streams)
                stream.Close();
            m_streans = null;
        }

        //Delete every file created by the stream
        foreach (string file in _emfFiles)
        {
            if (File.Exists(file))
                File.Delete(file);
        }
    }

最后在Disposed方法中调用了Run方法:

private void Run()
    {
        LocalReport report = new LocalReport();
        report.ReportPath = "Report.rdlc";
        report.DataSources.Add(new ReportDataSource("Sales", LoadSalesData()));

        Export(report);

        m_currentPageIndex = 0;
        Print();

        //After finishing printing delete those EMF files
        Disposed();
    }

这种方法适合我。希望它有所帮助..

答案 1 :(得分:0)

为什么使用FileStream而不是MemoryStream?

这对我有用:

 private Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek)
    {
        Stream stream = new MemoryStream();
        m_streams.Add(stream);
        return stream;
    }