987 Stimmen

Gibt es eine Möglichkeit zu überprüfen, ob eine Datei in Gebrauch ist?

Ich schreibe ein Programm in C#, das wiederholt auf 1 Bilddatei zugreifen muss. Die meiste Zeit funktioniert es, aber wenn mein Computer schnell läuft, wird es versuchen, auf die Datei zuzugreifen, bevor es zurück in das Dateisystem gespeichert wurde und einen Fehler ausgeben:

"Datei wird von einem anderen Prozess verwendet"

Ich würde gerne einen Weg finden, dies zu umgehen, aber alles, was ich gegoogelt habe, hat nur die Erstellung von Prüfungen mit Hilfe der Ausnahmebehandlung ergeben. Dies ist gegen meine Religion, so ich frage mich, ob jemand einen besseren Weg, es zu tun hat?

35 Stimmen

Sie können dies testen, indem Sie alle offenen Handles auf dem System untersuchen. Da es sich bei Windows jedoch um ein Multitasking-Betriebssystem handelt, besteht die Möglichkeit, dass direkt nach der Ausführung des Codes, mit dem festgestellt werden soll, ob die Datei geöffnet ist, ein Prozesscode mit der Verwendung dieser Datei beginnt und zu dem Zeitpunkt, zu dem Sie versuchen, sie zu verwenden, ein Fehler auftritt. Es ist jedoch nicht verkehrt, zuerst zu prüfen, ob die Datei geöffnet ist; gehen Sie nur nicht davon aus, dass sie nicht verwendet wird, wenn Sie sie tatsächlich benötigen.

6 Stimmen

Aber gerade für dieses spezielle Problem würde ich empfehlen, die Dateihandles nicht zu untersuchen und nur eine bestimmte Anzahl von Versuchen durchzuführen, z. B. 3-5, bevor sie fehlschlagen.

0 Stimmen

Wie wird diese Bilddatei erstellt? Können Sie Ihr Programm anhalten/schlafen/pausieren, bis die Erzeugung abgeschlossen ist? Das ist bei weitem der bessere Weg, um die Situation zu bewältigen. Wenn nicht, dann glaube ich nicht, dass Sie eine Ausnahmebehandlung vermeiden können.

0voto

Carra Punkte 17220

Versuchen Sie, die Datei in ein temporäres Verzeichnis zu verschieben/zu kopieren. Wenn Sie das können, hat die Datei keine Sperre und Sie können gefahrlos in dem temporären Verzeichnis arbeiten, ohne Sperren zu erhalten. Andernfalls versuchen Sie einfach, die Datei in x Sekunden erneut zu verschieben.

0voto

Tadej Punkte 5745

Würde so etwas helfen?

var fileWasWrittenSuccessfully = false;
while (fileWasWrittenSuccessfully == false)
{
    try
    {
        lock (new Object())
        {
            using (StreamWriter streamWriter = new StreamWriter("filepath.txt"), true))
            {
                streamWriter.WriteLine("text");
            }
        }

        fileWasWrittenSuccessfully = true;
    }
    catch (Exception)
    {

    }
}

-1voto

zzfima Punkte 1409

Ich verwende diesen Workaround, aber ich habe eine Zeitspanne zwischen der Überprüfung der Dateisperre mit der Funktion IsFileLocked und dem Öffnen der Datei. In dieser Zeitspanne kann ein anderer Thread die Datei öffnen, so dass ich IOException erhalten.

Deshalb habe ich extra Code dafür hinzugefügt. In meinem Fall möchte ich XDocument laden:

        XDocument xDoc = null;

        while (xDoc == null)
        {
            while (IsFileBeingUsed(_interactionXMLPath))
            {
                Logger.WriteMessage(Logger.LogPrioritet.Warning, "Deserialize can not open XML file. is being used by another process. wait...");
                Thread.Sleep(100);
            }
            try
            {
                xDoc = XDocument.Load(_interactionXMLPath);
            }
            catch
            {
                Logger.WriteMessage(Logger.LogPrioritet.Error, "Load working!!!!!");
            }
        }

Was meinen Sie dazu? Kann ich irgendetwas ändern? Vielleicht brauchte ich die Funktion IsFileBeingUsed gar nicht zu verwenden?

Gracias

-1voto

Vinney Kelly Punkte 4857

Ich bin gespannt, ob dies irgendwelche WTF-Reflexe auslöst. Ich habe einen Prozess, der ein PDF-Dokument aus einer Konsolenanwendung erstellt und anschließend startet. Ich hatte jedoch mit einer Schwachstelle zu kämpfen, bei der, wenn der Benutzer den Prozess mehrmals ausführt und dabei dieselbe Datei erzeugt, ohne die zuvor erzeugte Datei zu schließen, die Anwendung eine Ausnahme auslöst und stirbt. Dies trat relativ häufig auf, da die Dateinamen auf den Nummern der Verkaufsangebote basieren.

Anstatt auf so unschöne Weise zu scheitern, entschied ich mich, auf die automatische Versionserhöhung der Dateien zu setzen:

private static string WriteFileToDisk(byte[] data, string fileName, int version = 0)
{
    try
    {
        var versionExtension = version > 0 ? $"_{version:000}" : string.Empty;
        var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"{fileName}{versionExtension}.pdf");
        using (var writer = new FileStream(filePath, FileMode.Create))
        {
            writer.Write(data, 0, data.Length);
        }
        return filePath;
    }
    catch (IOException)
    {
        return WriteFileToDisk(data, fileName, ++version);
    }
}

Wahrscheinlich kann man sich etwas mehr Mühe geben mit der catch Block, um sicherzustellen, dass ich die richtige(n) IOException(s) abfange. Ich werde wahrscheinlich auch den App-Speicher beim Start löschen, da diese Dateien sowieso temporär sein sollen.

Mir ist klar, dass dies über den Rahmen der Frage des Auftraggebers hinausgeht, einfach zu prüfen, ob die Datei in Gebrauch ist, aber das war in der Tat das Problem, das ich lösen wollte, als ich hier ankam, so dass es vielleicht für jemand anderen nützlich ist.

-1voto

Ribaz Punkte 180
retry_possibility:
//somecode here

try
{
    using(FileStream stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None))
    {
        stream.Close();
    }
    //write or open your file here
}
catch (IOException)
{
    DialogResult dialogResult = MessageBox.Show("This file is opened by you or another user. Please close it and press retry.\n"+ expFilePath, "File Locked", MessageBoxButtons.RetryCancel);
    if (dialogResult == DialogResult.Retry)
    {
        goto retry_possibility;
    }
    else if (dialogResult == DialogResult.Cancel)
    {
        //do nothing
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X