Trying to REopen Sytem.IO Objects

时间:2015-10-29 15:51:49

标签: c# streamreader streamwriter system.io.file

I am making a program that allows you to roll five different types of multi sided "dice", and when you roll a number I want it to store it in a text file. There is a menu strip item at the top of my form that you click, it closes the StreamWriter and FileStream and opens a second form showing what numbers were rolled and by what die they were rolled ( I'm having it be just the numbers rolled now for simplicity's sake) and it displays fine. But when I close the Reader, Stream, and second form and go back to the first form, I try to Reopen the Writer and Stream and it tells me that is already in use.

My First Form's Code:

using System;
using System.Windows.Forms;
using System.IO;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private Random ran = new Random();
        static FileStream outFile = new FileStream(@"H:\C#\Independant Projects\VirtualDice\History.txt", FileMode.OpenOrCreate, FileAccess.Write);
        StreamWriter writer = new StreamWriter(outFile);

        private int ranNum;

        public Form1()
        {
            InitializeComponent();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            ranNum = ran.Next(1, 21);
            Display();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            ranNum = ran.Next(1, 13);
            Display();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            ranNum = ran.Next(1, 5);
            Display();
        }

        private void button4_Click(object sender, EventArgs e)
        {
            ranNum = ran.Next(1, 9);
            Display();
        }

        private void button5_Click(object sender, EventArgs e)
        {
            ranNum = ran.Next(1, 11);
            Display();
        }
        private void Display()
        {
            lblNum.Text = String.Format("{0}", ranNum);
            lblNum.Visible = true;
            writer.WriteLine(ranNum);
        }

        private void historyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            tabControl1.SelectedIndex = 1;
            writer.Close();
            outFile.Close();
            History history = new History();
            history.ShowDialog();
        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            FileStream outFile = new FileStream(@"H:\C#\Independant Projects\VirtualDice\History.txt", FileMode.OpenOrCreate, FileAccess.Write);
            StreamWriter writer = new StreamWriter(outFile);
            tabControl1.SelectedIndex = 0;
        }
    }
}

My Second Form's Code:

using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class History : Form
    {
        public History()
        {
            InitializeComponent();
        }

        static private FileStream inFile = new FileStream(@"H:\C#\Independant Projects\VirtualDice\History.txt", FileMode.Open, FileAccess.Read);
        private StreamReader reader = new StreamReader(inFile);

        private void History_Load(object sender, EventArgs e)
        {
            string item;

            item = reader.ReadLine();
            try
            {
                lstHistory.Items.Add(item);
            }
            catch (Exception)
            {
                lstHistory.Font = new Font(lstHistory.Font.Name, 12, lstHistory.Font.Unit);
                lstHistory.Items.Add("You have not rolled any numbers");
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

You need to release the unmanaged resources (in your case the file) properly once done with it. Call the Dispose() function on the stream once done with it:

if(inFile != null){
    inFile.Dispose();
}

And even better, wrap it in a using() like this:

using(FileStream outFile = new FileStream(@"H:\C#\Independant Projects\VirtualDice\History.txt", FileMode.OpenOrCreate, FileAccess.Write)){
    StreamWriter writer = new StreamWriter(outFile);
    tabControl1.SelectedIndex = 0;
}

using will automatically call Dispose() for you at the right time in the proper way (i.e. it checks if the object is null first before calling Dispose() on it to avoid a `null exception). Check this link for more details about the using statement.

However, if you have the same code in so many places, it is probably worth it to wrap it in a singleton pattern. Check this Microsoft article on how to write a singleton pattern in C#.