避免"文件被另一个进程使用" IO异常

时间:2017-08-22 11:57:15

标签: c# exception io wait ioexception

我在下面包含的代码成功写入CSV文件。但是,如果我写的CSV文件碰巧在Excel中打开,我会得到一个System.IO.Exception,表示"该文件正由另一个进程使用。"

如何更改代码以便程序继续运行并等到CSV不再在Excel中打开?

private void timer1_Tick(object sender, EventArgs e)
    {
        int actmonth, actyear, actsecond;
        System.DateTime fecha = System.DateTime.Now;
        actmonth = fecha.Month;
        actyear = fecha.Year;
        if (actmonth <= 9)
        {
            valorfechaact = System.Convert.ToString(actyear) + "00" + System.Convert.ToString(actmonth);
        }
        else
        {
            valorfechaact = System.Convert.ToString(actyear) + "0" + System.Convert.ToString(actmonth);
        }

        actsecond = fecha.Second;

        string label;
        label = label1.Text;
        string at = "@";
        string filename = valorfechaact + ".csv";

        string ruta3 = System.IO.Path.Combine(at, label, filename); 
        if (Directory.Exists(label1.Text))
        {
            StreamWriter wr = new StreamWriter(ruta3, true);
            wr.WriteLine("1asd" + actsecond);
            wr.Close();
            wr.Dispose();
        }
        else
        {
            System.Console.WriteLine("no se puede escribir en el archivo");
            timer1.Stop();
        }
    }

2 个答案:

答案 0 :(得分:1)

你可以看看这个问题:

https://github.com/liady/webpack-node-externals

讨论的方法之一是简单地尝试访问该文件。如果抛出异常,您可以等待再试一次。

如果您真的想等到工作簿可写,那么您可以这样做,例如通过使用while循环(可能你想要添加一个超时,或者如果相关提醒用户他/她需要在Excel中关闭文件)。 在代码中它可能是这样的:

int someLargeNumberOfIterations = 100000000;

while(FileIsLocked(filepath) && elapsedMs < timeoutMs) {
   Thread.SpinWait(someLargeNumberOfIterations);

   // Set elapsed
}

// Write the file

其中FileIsLocked是您根据上述帖子编写的函数,timeoutMs是一些适当的超时。

答案 1 :(得分:1)

您可以编写一个Methode,尝试使用FileStream打开File并返回一个布尔标志

可能的解决方案是

public static class FileInfoExtension
{
    public static bool IsLocked(this FileInfo file)
    {
        FileStream stream = null;
        try
        {
            stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None);
        }
        catch (IOException)
        {
            return true;
        }
        finally
        {
            stream?.Close();
        }
        return false;
    }
}

然后你可以使用它

    var fileInfo = new FileInfo(ruta3);
    if (!fileInfo.IsLocked())
    {
       // do code
    }

一个非常简单(和糟糕)的等待解决方案是

    while (file.IsLocked())
    {
       Thread.Sleep(100);
    }

一般是您的代码不清楚且难以阅读。

你有很多的还原代码,很少有变量被命名。 也许这个Guidline可以帮助你https://github.com/dennisdoomen/CSharpGuidelines

可能有一个更清晰的解决方案

    private void timer1_Tick(object sender, EventArgs e)
    {
        var directory = label1.Text;
        if (!Directory.Exists(directory))
        {
            Console.WriteLine("no se puede escribir en el archivo");
            timer1.Stop();
            return;
        }
        var now = DateTime.Now;
        _valorfechaact = now.Month <= 9 ? $"{now.Year}00{now.Month}" : $"{now.Year}0{now.Month}";
        var fullname = Path.Combine("@", directory, $"{_valorfechaact}.csv");
        var fileInfo = new FileInfo(fullname);
        if (fileInfo.IsLocked())
        {
            Console.WriteLine($"The File {fullname} is locked!");
            return;
        }
        using (var wr = new StreamWriter(fullname, true))
        {
            wr.WriteLine("1asd" + now.Second);
        }
    }