1

我正在从控制台应用程序打印报告。我开始使用微软规定的方式(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% 返回异常,报告该文件不可访问,因为它已被另一个进程打开。即使先前的流已被处理。

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

4

2 回答 2

2

我面临同样的问题,并从另一种方式出来。我按照这种方法引用了您的链接..

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

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

这种方法对我有用。希望能帮助到你..

于 2013-05-31T11:28:52.133 回答
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;
    }
于 2014-07-03T19:04:34.507 回答