简体   繁体   English

Filestream.write()的File.Delete问题

[英]File.Delete issue with filestream.write()

I have refresh button. 我有刷新按钮。 On refresh, I need to download a file and de-serialize its contents to read the information in it. 刷新后,我需要下载文件并反序列化其内容以读取其中的信息。 Below is the method used to download the file. 以下是用于下载文件的方法。

public void DownloadVersionContents(long fileID,string fileName)
        {
            if (File.Exists(path))
              {
                 File.Delete(path);
              }
            Stream stream = service.DownloadContent(fileID);

            using (FileStream fileStream = File.OpenWrite(fileName))
            {
                // Write the stream to the file on disk.
                var buf = new byte[1024];
                int numBytes;
                while ((numBytes = stream.Read(buf, 0, buf.Length)) > 0)
                {
                    fileStream.Write(buf, 0, numBytes);
                }
                fileStream.Close();
            }
            stream.Close();
        }

Everytime the refresh button is clicked, I have to delete the file and download latest file from the server. 每次单击刷新按钮时,我都必须删除文件并从服务器下载最新文件。 If the refresh is called with in a second or two im getting an error saying 如果在一两秒钟内调用刷新,我会收到错误消息

System.IO.IOException was caught
  HResult=-2147024864
  Message=The process cannot access the file 'C:\Users\...\AppData\Local\Temp\mapping - copy.xml' because it is being used by another process.
  Source=mscorlib
  StackTrace:
       at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
       at System.IO.File.InternalDelete(String path, Boolean checkHost)
       at System.IO.File.Delete(String path)

If the refresh is called after at least 10 or 20 seconds,im not getting any error. 如果在至少10或20秒后调用刷新,则表示没有任何错误。 The file is never opened nor used yet. 该文件从未打开或使用过。 Kindly help. 请帮助。 Edit: Sorry I forgot to mention, Im de-serializing the file using this method immediately after refresh is called. 编辑:对不起,我忘了提及,在刷新被调用后,我立即使用此方法对文件进行反序列化。

public static T DeSerializeFromFile<T>(string xmlFilePath) 
        {
            T instance = default(T);

            if (xmlFilePath != null)
            {
                var reader = new StreamReader(xmlFilePath);
                var serializer = new XmlSerializer(typeof(T));
                instance = (T)serializer.Deserialize(reader);
            }
            return instance;
        }

The refresh button is called again after the values are updated. 值更新后,再次调用刷新按钮。

It sounds like the file takes longer than a couple seconds to get written. 听起来文件要花费超过几秒钟的时间才能被写入。 If the file is still being written to, then no, you certainly won't be able to delete it. 如果仍在写入文件,则不会,您当然无法删除它。 You have a couple options. 您有两种选择。

The simplest, and probably best, is to keep track of whether you're still writing to it. 最简单(可能也是最好)是跟踪您是否仍在写它。

private bool IsWriting = false;
public void DownloadVersionContents(long fileID, string fileName)
{
    if (!IsWriting)
    {
        IsWriting = true;

        // Perform the delete and download

        IsWriting = false;
    }
}

Depending on the platform, you might want to reflect this in the UI as well, perhaps by disabling the "Refresh" button. 根据平台的不同,您可能还希望通过禁用“刷新”按钮在UI中反映出来。 This, of course, is assuming the file doesn't change more frequently than the time it takes to update. 当然,这是假设文件更改的频率不超过更新时间。 If it does, you may want to implement some cancellation pattern. 如果是这样,您可能要实现一些取消模式。

Beyond that, you could buffer the file directly into memory, then write it "all at once," which would probably only take a fraction of a second. 除此之外,您可以将文件直接缓冲到内存中,然后“一次全部写入”,这可能只需要一秒钟的时间。 Of course, if it's a big file, that won't be feasible. 当然,如果文件很大,那将是不可行的。

This seems like a good time to use a try catch -block. 这似乎是使用try catch -block的好时机。 Catch the exception and prompt the user if the file is busy. 捕获异常,并在文件繁忙时提示用户。

try
{
    if (File.Exists(path))
         File.Delete(path);

    using(Stream stream = service.DownloadContent(fileID))
    {
        using (FileStream fileStream = File.OpenWrite(fileName))
        {
            // Write the stream to the file on disk.
            var buf = new byte[1024];
            int numBytes;
            while ((numBytes = stream.Read(buf, 0, buf.Length)) > 0)
            {
                fileStream.Write(buf, 0, numBytes);
            }
        }
    }
}
catch (IOException e)
{
    MessageBox.Show("The refresh failed, try again in a few seconds."); 
}

This wont speed up the refresh process but it will prevent the user from crashing your program by spamming refresh. 这不会加快刷新过程,但可以防止用户通过向刷新发送垃圾邮件来使您的程序崩溃。 Try to always have this kind of exception handling present when working with outside sources. 在使用外部源时,请尝试始终提供这种异常处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM