我正在从控制台应用程序打印报告。我开始使用微软(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%会返回异常,报告该文件无法访问,因为它是由另一个文件打开的处理。即使先前的流已被处置。
我该怎么做才能解决这个问题?
答案 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;
}