FileStream.Close()不关闭文件句柄瞬间 [英] FileStream.Close() is not closing the file handle instantly

查看:450
本文介绍了FileStream.Close()不关闭文件句柄瞬间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我读的数据块的源文件,并把它传递给WCF服务在某些远程SMB写下来。我保持开放的FileStream,直到所有的数据被写入。

打开和关闭文件处理多个时间下降的表现让我下面这个方法。

在所有的数据被写入,我叫CloseHandle的()。然后,我可能需要通过调用DoSomeOperation上执行同一个文件中的一些其他操作()。正如我已经关闭了文件句柄中调用CloseHandle()函数,但我得到的错误的文件是与其他进程使用的DoSomeOperation()。如果我有些延迟后调用DoSomeOperation(),那么问题是不存在的。

请帮助我们立即关闭文件句柄,我叫FileStream.Close()。

这code段是一个大计划的一部分,所以我不能提及所有的code在这里。

  //在WCF服务
的FileStream FS = NULL;
公共无效对appendBytes(字符串文件名,byte []的数据,好仓)
{
    尝试
    {
        如果(FS == NULL)//在第一次调用,打开文件句柄
            FS = System.IO.File.Open(文件名,System.IO.FileMode.Append,System.IO.FileAccess.Write,System.IO.FileShare.None);

        fs.Write(数据,0,data.Length);
    }
    赶上(例外前)
    {
        //关闭处理错误的情况下
        如果(FS!= NULL)
            fs.Close();
    }
}

公共无效CloseHandle的()
{
    //关闭手柄明确
    如果(FS!= NULL)
        fs.Close();
}

公共无效DoSomeOperation(字符串文件名)
{
    使用(FSO的FileStream = System.IO.File.Open(文件名,System.IO.FileMode.Append,System.IO.FileAccess.Write,System.IO.FileShare.None))
    {
        //做一些与这里的文件,这是原子操作,所以我开的FileStream以'使用'处置的操作结束
    }
}

//在客户端
公共无效CallerFunction()
{
    //读取数据的资源文件中块和拷贝使用WCF.AppendBytes另一台机器的目标文件
    WCF.AppendBytes(文件名,数据,POS);
    WCF.CloseHandle();
    WCF.DoSomeOperation(文件名); //我得到的错误在这里,文件是与其他一些工艺中使用。如果我把一个Thread.sleep代码(1000)就在这个声明在此之前,一切工作正常。
}
 

我已经写了一个小的测试code重现同样的场景在控制台应用程序:只需调用TestHandleClose()从主(),它将一些周期后,给误差

 静态无效TestHandleClose()
        {
            INT I = 0;
            尝试
            {

                如果(File.Exists(@D:\目标\ file2.exe))
                    File.Delete(@D:\目标\ file2.exe);

                byte []的数据= NULL;
                INT块大小= 10 * 1024 * 1024;

                对于(i = 0; I< 100;我++)
                {
                    使用(FR的FileStream = File.open方法(@D:\目标\ File1.zip,FileMode.Open,FileAccess.Read,FileShare.None))
                    {
                        数据=新的字节[块大小]
                        fr.Read(数据,0,块大小); //我们正在阅读的文件一个时间,但附加相同的数据到目标文件的多个时间。

                        使用(的FileStream F = File.open方法(@D:\目标\ file2.exe,FileMode.Append,FileAccess.Write,FileShare.None))
                        {
                            f.Write(数据,0,data.Length); //我们正在编写相同的数据多次。
                            f.Flush();
                            f.Close();
                        }
                    }

                }

                如果(File.Exists(@D:\目标\ file2.exe))
                    File.Delete(@D:\目标\ file2.exe);

            }
            赶上(例外前)
            {
                扔;
            }
        }
 

解决方案

最后的样品code的帮助下,我是pretty的肯定,我有你的问题。

的事情是,即使是最新的样品code未能重现。然而,它显示了另一件事,你可能错过了 - 你写的文件是的.exe 。为什么这是一个问题吗?嗯,有几个原因,但其中之一是,当你列出的目录,其中的.exe 文件正在使用浏览器,浏览器继续运行并尝试读取它(得到的图标)。在这么短的时间,该文件无法打开与 FileShare.None (事实​​上, FileShare.Read 可能会没有帮助,因为它很可能谁打开了它没有具体说明 FileShare.ReadWrite )。

所以再次,的FileStream 关闭就好了,而且效果很好(摆脱刷新关闭通话,虽然 - 他们是在浪费性能,没用)。的问题是,另一个进程试图读取在此期间该文件。它可能会像在我的情况(资源管理器中,总指挥官,...),这可能是一些 FileSystemWatcher的你有地方,它可能是一个病毒扫描程序(一些文件管理器虽然大多数病毒扫描程序现在使用卷影副本),它可能是自动创建缩图,等等。但是,code您发布自己根本不会引起问题 - 这是别人抓住你的文件

有两种基本选择,您都 - 要么保留该文件打开的全部时间,你需要它,或治疗 IOException异常临时,然后重试几次在给定的时间间隔。这就是你应该做的反正,而不是依靠的道路上快乐, - 大多数读者只允许并行读取,写入不

I am reading source file in chunks and pass it to WCf service to write down on some remote SMB. I am keeping open the FileStream until all data is written.

Opening and closing file handle multiple time decrease performance so I am following this approach.

Once all data is written, I call CloseHandle(). Then I may need to perform some other operation on same file by calling DoSomeOperation(). As I have closed the file handle in CloseHandle() function, but I get the error "file is in use with some other process" in DoSomeOperation(). If I call DoSomeOperation() after some delay then issue is not there.

Please help us to close the file handle instantly as I call FileStream.Close().

This code snippet is part of a big program, so I can't mention all the code here.

//In WCF service
FileStream fs = null;
public void AppendBytes(string fileName, byte[] data, long position)
{
    try
    {
        if (fs==null)//In first call, open the file handle
            fs = System.IO.File.Open(fileName, System.IO.FileMode.Append, System.IO.FileAccess.Write, System.IO.FileShare.None);

        fs.Write(data, 0, data.Length);
    }
    catch (Exception ex)
    {
        //Close handle in case of error
        if (fs != null)
            fs.Close();
    }
}

public void CloseHandle()
{
    //Close handle explicitly
    if (fs != null)
        fs.Close();
}

public void DoSomeOperation(string fileName)
{
    using (FileStream fsO = System.IO.File.Open(fileName, System.IO.FileMode.Append, System.IO.FileAccess.Write, System.IO.FileShare.None))
    {
        //Do something with file here, this is atomic operation so I am opening FileStream with 'using' to dispose at operation is over
    }
}

//In client
public void CallerFunction()
{
    //Read Data from sourceFile in chunk and copy to target file using WCF.AppendBytes on another machine
    WCF.AppendBytes(filename, data, pos);
    WCF.CloseHandle();
    WCF.DoSomeOperation(filename); //I get error here that file is in use with some other process. if I put a thread.sleep(1000) just before this statement then all works fine.
}

I have written a small test code to reproduce the same scenario on console application: Just Call TestHandleClose() from Main(), it will give error after some cycles.

 static  void TestHandleClose()
        {
            int i = 0;
            try
            {

                if (File.Exists(@"d:\destination\file2.exe"))
                    File.Delete(@"d:\destination\file2.exe");

                byte[] data = null;
                int blocksize = 10 * 1024 * 1024;

                for( i=0;i<100;i++)
                {
                    using (FileStream fr = File.Open(@"d:\destination\File1.zip", FileMode.Open, FileAccess.Read, FileShare.None))
                    {
                        data = new byte[blocksize];
                        fr.Read(data, 0, blocksize); //We are reading the file single time but appending same data to target file multiple time.

                        using (FileStream f = File.Open(@"d:\destination\file2.exe", FileMode.Append, FileAccess.Write, FileShare.None))
                        {
                            f.Write(data, 0, data.Length); //We are writing same data multiple times.
                            f.Flush();
                            f.Close();
                        }
                    }

                }

                if (File.Exists(@"d:\destination\file2.exe"))
                    File.Delete(@"d:\destination\file2.exe");

            }
            catch (Exception ex)
            {
                throw;
            }
        }

解决方案

The final sample code helped, I'm pretty sure I have your problem.

The thing is, even the latest sample code fails to reproduce. However, it shows another thing that you probably missed - the file you're writing is .exe. Why is this a problem? Well, there's a couple of reasons, but one of those is that when you list the directory where the .exe file is using explorer, explorer goes ahead and tries to read it (to get the icon). In this short time, the file cannot be opened with FileShare.None (and in fact, FileShare.Read probably will not help either, since it's quite likely whoever opened it didn't specify FileShare.ReadWrite).

So yet again, FileStream is closed just fine, and works well (get rid of the Flush and Close calls, though - they're wasting performance, and useless). The problem is that another process tries to read the file in the meantime. It might be some file manager like in my case (Explorer, Total Commander, ...), it might be some FileSystemWatcher you have somewhere, it might be a virus scanner (though most virus scanners nowadays use shadow copies), it might be something that automatically creates thumbnails for images, etc.. But the code you posted yourself simply doesn't cause the problem - it's someone else grabbing your file.

There's basically two options you have - either keep the file opened the whole time you need it, or treat the IOException as temporary and retry a few times in a given interval. That's what you should be doing anyway, instead of relying on the path being happy - most readers only allow concurrent reads, not writes.

这篇关于FileStream.Close()不关闭文件句柄瞬间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆