Say I want to define a TempFileStream class that creates a temporary file using Path.GetTempFileName() method. A temporary file must be deleted when TempFileStream\'s object
I know this is an older thread, but here's an alternate solution. I started to implement the TempFileStream, but I wanted more concurrency. My use-case involves exporting [potentially MBs of] database results to a CSV file via MVC. I want to begin downloading to the client as soon as data are available from the database query rather than wait for a potentially large temp file to be written before I start downloading.
In this solution, I launch the query in a separate thread which fills an AnonymousPipeStream. The main thread can then slurp the data from the other end of the pipe as its available. It uses .Net 4 Tasks.
Hope someone else finds this useful.
-Rob
Controller method:
public FileResult ResultExport ( ReportOptions options )
{
ResultExport rpt = new ResultExport( options );
HttpContext.Response.BufferOutput = false;
return File( rpt.Export(), "text/csv", "results.csv" );
}
Model:
public ResultExport
{
private AnonymousPipeServerStream WriteStream = null;
public Stream Export()
{
//
// We'll fire off the database query in a background
// thread. It will write data to one end of the pipe. We'll return the reader
// end of that pipe to our caller.
//
WriteStream = new AnonymousPipeServerStream( PipeDirection.Out );
AnonymousPipeClientStream reader = new AnonymousPipeClientStream( PipeDirection.In, WriteStream.ClientSafePipeHandle );
//
// Call Execute() in a background thread.
//
Task.Factory.StartNew( () => Execute() );
//
// While Execute() is filling the pipe with data,
// return the reader end of the pipe to our caller.
//
return reader;
}
private void Execute ()
{
//
// WriteStream should only by populated by Export()
//
if( WriteStream != null )
{
using ( StreamWriter sw = new StreamWriter( WriteStream, Encoding.UTF8, 4096 ) )
{
//
// Shove data into the StreamWriter as we get it from the database
//
foreach ( string line in ExportCore() )
{
// Each line is a comma-delimited set of values
sw.WriteLine( line );
}
}
}
}
}