当批量打印来自控制台应用程序的RDLC报告时处理流

本文关键字:RDLC 报告 处理 应用程序 控制台 打印 | 更新日期: 2023-09-27 18:13:25

我正在从控制台应用程序打印报告。我开始使用微软规定的方式(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个单页报告。显然,如果不严重降低性能,我就不能让所有这些流保持开放状态。所以,我修改了一些东西。我创建了一个类级流对象(RenderStream),我在CreateStream回调中使用,并将文件名保存在集合中。

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);
    }
}

现在,这就是问题所在。虽然I 通常打开流到那些呈现的文件没有问题,但在打印时访问这些文件的尝试中,约有5%返回异常,报告文件不可访问,因为它被另一个进程打开了。

我能做些什么来解决这个问题?

当批量打印来自控制台应用程序的RDLC报告时处理流

我面对同样的问题,从另一种方式出来。参考你的链接,我遵循了这种方法。

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

 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);
        }
    }

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

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();
    }

这个方法适合我。

为什么使用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;
    }