Попытка открыть объекты Sytem.IO

Я делаю программу, которая позволяет вам бросать пять разных типов многогранных "кубиков", и когда вы бросаете число, я хочу, чтобы оно сохранялось в текстовом файле. В верхней части моей формы есть элемент полосы меню, который вы нажимаете, он закрывает StreamWriter и FileStream и открывает вторую форму, показывающую, какие числа были прокручены и на какой кубик они были прокручены (я имею в виду, что это просто свернутые числа теперь для простоты) и это отображает нормально. Но когда я закрываю Reader, Stream и вторую форму и возвращаюсь к первой форме, я пытаюсь снова открыть Writer и Stream, и она сообщает мне, что она уже используется.

Код моей первой формы:

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

Код моей второй формы:

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 ответ

Вам нужно правильно высвободить неуправляемые ресурсы (в вашем случае файл), как только это будет сделано. Позвоните Dispose() функция на stream как только закончите с этим:

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

И даже лучше, заверните его в using() как это:

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 автоматически позвонит Dispose() для вас в нужное время надлежащим образом (т.е. он проверяет, является ли объект null сначала перед звонком Dispose() на нем, чтобы избежать `нулевого исключения). Проверьте эту ссылку для более подробной информации об использовании оператора.

Однако, если у вас есть один и тот же код во многих местах, возможно, стоит его обернуть singleton шаблон. Прочтите эту статью Microsoft о том, как написать шаблон синглтона в C#.

Другие вопросы по тегам