Check If File Is In Use By Other Instances of Executable Run

自作多情 提交于 2020-01-25 13:06:31

问题


Before I go into too detail, my program is written in Visual Studio 2010 using C# .Net 4.0.

I wrote a program that will generate separate log files for each run. The log file is named after the time, and accurate up at millisecond (for example, 20130726103042375.log). The program will also generate a master log file for the day if it has not already exist (for example, *20130726_Master.log*)

At the end of each run, I want to append the log file to a master log file. Is there a way to check if I can append successfully? And retry after Sleep for like a second or something?

Basically, I have 1 executable, and multiple users (let's say there are 5 users).

All 5 users will access and run this executable at the same time. Since it's nearly impossible for all user to start at the exact same time (up to millisecond), there will be no problem generate individual log files.

However, the issue comes in when I attempt to merge those log files to the master log file. Though it is unlikely, I think the program will crash if multiple users are appending to the same master log file.

The method I use is

File.AppendAllText(masterLogFile, File.ReadAllText(individualLogFile));

I have check into the lock object, but I think it doesn't work in my case, as there are multiple instances running instead of multiple threads in one instance.

Another way I look into is try/catch, something like this

try
{
    stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
catch {}

But I don't think this solve the problem, because the status of the masterLogFile can change in that brief millisecond.

So my overall question is: Is there a way to append to masterLogFile if it's not in use, and retry after a short timeout if it is? Or if there is an alternative way to create the masterLogFile?

Thank you in advance, and sorry for the long message. I want to make sure I get my message across and explain what I've tried or look into so we are not wasting anyone's time.

Please let me know if there's anymore information I can provide to help you help me.


回答1:


Your try/catch is the way to do things. If the call to File.Open succeeds, then you can write to to the file. The idea is to keep the file open. I would suggest something like:

bool openSuccessful = false;
while (!openSuccessful)
{
    try
    {
        using (var writer = new StreamWriter(masterlog, true)) // append
        {
            // successfully opened file
            openSuccessful = true;
            try
            {
                foreach (var line in File.ReadLines(individualLogFile))
                {
                    writer.WriteLine(line);
                }
            }
            catch (exceptions that occur while writing)
            {
                // something unexpected happened.
                // handle the error and exit the loop.
                break;
            }
        }
    }
    catch (exceptions that occur when trying to open the file)
    {
        // couldn't open the file.
        // If the exception is because it's opened in another process,
        // then delay and retry.
        // Otherwise exit.
        Sleep(1000);
    }
}
if (!openSuccessful)
{
    // notify of error
}

So if you fail to open the file, you sleep and try again.

See my blog post, File.Exists is only a snapshot, for a little more detail.




回答2:


I would do something along the lines of this as I think in incurs the least overhead. Try/catch is going to generate a stack trace(which could take a whole second) if an exception is thrown. There has to be a better way to do this atomically still. If I find one I'll post it.



来源:https://stackoverflow.com/questions/17885732/check-if-file-is-in-use-by-other-instances-of-executable-run

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!