首页 > 解决方案 > 当我尝试使用线程重命名我的文件名并关闭并刷新 FileStream 时,它会给我错误 Cannot access a closed file

问题描述

我有大量数据,我需要每 5 秒制作一次“.txt”文件,并将下一个数据写入新创建的“.txt”文件中,但是当我尝试使用 Timer 线程时,有时程序运行正常但是一段时间后,它将通过异常无法访问已关闭的文件。请在我的代码中帮助我并建议我必须做什么。

public class Program
    {
        public static void Main(string[] args)
        {
            Service s = new Service();
            s.init();
        }
    }


    class Service
    {
        FileStream fs = null;
        int filecount = 0;
        long a = 1000000000000000;
      // int j = 0;

        public void  init()
        {
            initialiseFile(filecount);
            timer();
            WriteINFile();
        }

        private void initialiseFile( int filecount)
        {

                fs = File.Create("C:\\Users\\yogesh.ghonate\\source\\repos\\ConsoleApp3\\ConsoleApp3\\NewFolder1\\Index_" + filecount + ".txt");        
        }
        private void WriteINFile()
        {
            string sen = " write in file ";

                for (int i = 0; i < a; i++)
                {
                    Byte[] title = new UTF8Encoding(true).GetBytes(sen);

                    fs.Write(title, 0, title.Length);
                }
        }

        public void timer()
        {
            System.Timers.Timer th = new System.Timers.Timer();
            th.Interval = 5000;
            th.Elapsed += new ElapsedEventHandler(run);
            th.Start();         
            run(th, null);
        }

        public void run(object state, ElapsedEventArgs e)
        {
            Commitzfile();
        }

        private void Commitzfile()
        {

            //Stopwatch stopwatch = new Stopwatch();
            //stopwatch.Start();
            fs.Flush();
            fs.Close();
            // fs.Dispose();
            //stopwatch.Stop();
            filecount++;
            initialiseFile(filecount);

        }
    }

标签: c#asp.netmultithreading

解决方案


最严格的解决方案是添加lock到您的代码中。这将防止任何竞争条件,也会使您的代码变慢一点,因为它会在资源正在使用时阻塞线程。

你可以像这样使用它:

// add new lock object
object lockObject = new object();
FileStream fs = null;
int filecount = 0;
long a = 1000000000000000;

…

private void WriteINFile()
{
    string sen = " write in file ";

    for (int i = 0; i < a; i++)
    {
        Byte[] title = new UTF8Encoding(true).GetBytes(sen);
        lock (lockObject)
        {
            fs.Write(title, 0, title.Length);
        }
    }
}

…

private void Commitzfile()
{
    lock(lockObject)
    {
        fs.Flush();
        fs.Close();
        filecount++;
        initialiseFile(filecount);
    }
}

我建议您阅读以下有关lock 语句的文档


更新

在并发编程中,有许多问题需要考虑。其中之一是资源管理。通常这个问题是与哲学家就餐问题一起出现的。当一个资源被多个进程/线程尝试使用时,主要问题就会发生,但该资源必须一次被一个使用。在您的情况下,它是 FileStream,因为一个线程一直在尝试写入它,而在另一个线程上它是关闭并更改的。您可以看到,在某些情况下,可能会发生一个关闭流而另一个仍试图同时写入它的情况。要克服这个问题,您需要确保一次只能由一个线程访问资源。执行此操作的一种工具是 lock 语句。

其他要记住的事情:

  • 死锁。
  • 有多少并发线程值得同时运行。

希望这个简短的总结有所帮助。如果您需要更多信息,请随时提出新问题(或查找是否已有问题)。


推荐阅读