File.Delete与filestream.write()的问题

时间:2015-03-27 09:09:57

标签: c# .net

我有刷新按钮。在刷新时,我需要下载一个文件并对其内容进行反序列化以读取其中的信息。以下是用于下载文件的方法。

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

每次单击刷新按钮时,我都必须删除该文件并从服务器下载最新文件。如果在一两秒内调用刷新,则会出现错误

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)

如果在至少10或20秒后调用刷新,则不会出现任何错误。该文件永远不会打开也不会使用。请帮助。 编辑: 抱歉,我忘了提及,我在调用刷新后立即使用此方法对文件进行反序列化。

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

更新值后再次调用刷新按钮。

2 个答案:

答案 0 :(得分:0)

听起来这个文件需要花费的时间超过几秒钟。如果文件仍然被写入,那么不,你肯定无法删除它。你有几个选择。

最简单,也可能最好的是跟踪你是否还在写它。

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

        // Perform the delete and download

        IsWriting = false;
    }
}

根据平台的不同,您可能希望在UI中反映这一点,也许可以通过禁用“刷新”按钮来实现。当然,这是假设文件的更改频率不会超过更新所需的时间。如果是,您可能想要实现一些取消模式。

除此之外,您可以将文件直接缓冲到内存中,然后“一次性”写入,这可能只需要几分之一秒。当然,如果它是一个大文件,那将是不可行的。

答案 1 :(得分:0)

这似乎是使用try catch块的好时机。捕获异常并在文件繁忙时提示用户。

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."); 
}

这不会加快刷新过程,但会阻止用户通过垃圾邮件刷新来破坏您的程序。尝试在与外部资源合作时始终存在此类异常处理。