需要关闭在同一个应用程序的另一个上下文中打开的文件流

时间:2013-12-07 00:55:12

标签: c# filestream

我有一个主窗口,用户单击该按钮处理选定的输入文件。按钮触发的代码块打开输入文件,输出文件和日志文件。同一个代码块一次读取一行输入文件的行,对每行的字段进行一些操作,然后将相应的行写入输出文件。错误消息将写入日志文件。处理单个文件可能需要几分钟。

如果用户不耐烦,我希望能够优雅地关闭3个文件,并使用红色的“X”按钮关闭主窗口。我有一个事件处理程序捕获单击“X”,但我无法引用我想要关闭的3个文件流,因为它们是在事件处理程序的上下文之外创建的。如何将3个文件流传递给处理程序?

namespace less
{
   public partial class MainWindow : Window
   {
        ...

        private static string filename;

        ...

      public MainWindow()
      {

            InitializeComponent();

            // string filename is chosen in this block of code

      }

    private void convertData_Click(object sender, RoutedEventArgs e)
        {
            // This is invoked when user clicks the "Process Data" button

            System.IO.StreamReader inputFile = new System.IO.StreamReader(filename);
            System.IO.StreamWriter outputFile = new System.IO.StreamWriter(filename + ".less.csv");
            System.IO.StreamWriter logFile = new System.IO.StreamWriter(filename + ".log");

                     ....

               <process all the data>

                     ....

           inputFile.Close();  // <- this works
           outputFile.Close();  // <- this works
           logFile.Close();  // <- this works

           this.Close();
         }

    private void MainWindow_Closed(object sender, EventArgs e)
        {

           // This is the event handler invoked when the red "X" is clicked.

           inputFile.Close(); // <- this (and following) do not work
           outputFile.Close();
           logFile.Close();
        }

   } // closes public partial class MainWindow : Window

} // closes namespace

3 个答案:

答案 0 :(得分:3)

当然它不起作用。这三个变量是方法convertData_Click的本地变量,因此无法在该方法之外引用。如果你真的想这样做,你需要将三个变量移动到变量filename的同一级别。它们成为全局类级变量,可以在该类的任何方法中引用。

说,我真的建议避免这种情况。 FileStream应该在需要时声明,使用,关闭和处理,并且在表单生命周期内不保持打开状态

namespace less
{
   public partial class MainWindow : Window
   {
        ...

       // Now these are global class level variables...
       // But again, don't do that.....
       private StreamReader inputFile;
       private StreamWriter outputFile;
       private StreamWriter logFile;

       private static string filename;

        ...
   }

更好的方法是

private void convertData_Click(object sender, RoutedEventArgs e)
{
   using(StreamReader inputFile = new System.IO.StreamReader(filename))
   using(StreamWriter outputFile = new System.IO.StreamWriter(filename + ".less.csv"))
   using(StreamWriter logFile = new System.IO.StreamWriter(filename + ".log"))
   {
        ....
        <process all the data>
        ....
   }
}

首选using语句是因为在处理数据时,如果出现异常,它也会关闭并销毁定义行中使用的变量

答案 1 :(得分:0)

它只是一个范围混合:

第一步:将其放入类范围

System.IO.StreamReader inputFile;
System.IO.StreamWriter outputFile;
System.IO.StreamWriter logFile;

第二步:替换

System.IO.StreamReader inputFile = new System.IO.StreamReader(filename);
System.IO.StreamWriter outputFile = new System.IO.StreamWriter(filename + ".less.csv");
System.IO.StreamWriter logFile = new System.IO.StreamWriter(filename + ".log");

inputFile = new System.IO.StreamReader(filename);
outputFile = new System.IO.StreamWriter(filename + ".less.csv");
logFile = new System.IO.StreamWriter(filename + ".log");

第三步:确保文件真正开放!使用try / catch构造或使用

if (inputFile != null) inputFile.Dispose();

和朋友

答案 2 :(得分:0)

您正在事件处理程序中创建FileStream对象,因此它们仅存在于该事件处理程序的范围内,然后由垃圾收集器标记为收集。你已经在处理程序的末尾关闭了流,所以即使你试图在方法之外访问它们,它们也会被关闭,所以这归结为几个与C#中的IDisposable模式相关的关键点

文件流实现IDisposable接口。这意味着它们可以保证具有Dispose方法。 Dispose是一种清除对象所需的任何资源的方法。例如,在FileStreams的情况下,Dispose方法关闭流。 using关键字可以在任何实现IDisposable的地方执行。该关键字用作:

using(StreamReader reader = new StreamReader(filename))
{
    // Reading the stream
}

你可以用以下内容代替:

try
{
    StreamReader reader = new StreamReader(filename);
   // Reading the stream
}
finally
{
    if(reader != null)
    {
        reader.Dispose();
    }
}

这实际意味着您不再需要担心关闭流,因为即使在读取期间抛出异常,也会调用Dispose方法。方便,没有?

如果您坚持要关闭事件处理程序之外的流,则需要将流定义移出到类范围。这并不能让你免于IDisposable的乐趣,因为每当你有一个包含IDisposable对象的类时,该类就需要实现IDisposable。并且该类的Dispose方法应该在Disposable成员对象上调用Dispose。 IDispospos是具有传染性的,并通过堆栈向上传播,直到您保证处置。如果你只使用该方法范围内的对象,你将为自己节省很多乐趣。