una soporta segundo rapida por optimizar mas lentas lenta hacer cuello cuantas consultas consulta como botella agilizar c# winforms file-io ioexception

c# - soporta - optimizar consultas mysql explain



Espere a que el archivo se libere por proceso (8)

¿Cómo espero a que el archivo sea libre para que ss.Save() pueda sobrescribirlo con uno nuevo? Si ejecuto esto dos veces juntas (ish) obtengo un error generic GDI+ .

///<summary> /// Grabs a screen shot of the App and saves it to the C drive in jpg ///</summary> private static String GetDesktopImage(DevExpress.XtraEditors.XtraForm whichForm) { Rectangle bounds = whichForm.Bounds; // This solves my problem but creates a clutter issue //var timeStamp = DateTime.Now.ToString("ddd-MMM-dd-yyyy-hh-mm-ss"); //var fileName = "C://HelpMe" + timeStamp + ".jpg"; var fileName = "C://HelpMe.jpg"; File.Create(fileName); using (Bitmap ss = new Bitmap(bounds.Width, bounds.Height)) using (Graphics g = Graphics.FromImage(ss)) { g.CopyFromScreen(whichForm.Location, Point.Empty, bounds.Size); ss.Save(fileName, ImageFormat.Jpeg); } return fileName; }


Aquí hay una solución que puede ser excesiva para algunos usuarios. Creé una nueva clase estática que tiene un evento que se activa solo cuando el archivo termina de copiarse.

El usuario registra los archivos que desea ver llamando a FileAccessWatcher.RegisterWaitForFileAccess(filePath) . Si el archivo aún no se está viendo, se inicia una nueva tarea que verifica repetidamente el archivo para ver si se puede abrir. Cada vez que lo comprueba, también lee el tamaño del archivo. Si el tamaño del archivo no aumenta en un tiempo predefinido (5 minutos en mi ejemplo), se sale del ciclo.

Cuando el ciclo sale del archivo al que se puede acceder o desde el tiempo de espera, se desencadena el evento FileFinishedCopying .

public class FileAccessWatcher { // this list keeps track of files being watched private static ConcurrentDictionary<string, FileAccessWatcher> watchedFiles = new ConcurrentDictionary<string, FileAccessWatcher>(); public static void RegisterWaitForFileAccess(string filePath) { // if the file is already being watched, don''t do anything if (watchedFiles.ContainsKey(filePath)) { return; } // otherwise, start watching it FileAccessWatcher accessWatcher = new FileAccessWatcher(filePath); watchedFiles[filePath] = accessWatcher; accessWatcher.StartWatching(); } /// <summary> /// Event triggered when the file is finished copying or when the file size has not increased in the last 5 minutes. /// </summary> public static event FileSystemEventHandler FileFinishedCopying; private static readonly TimeSpan MaximumIdleTime = TimeSpan.FromMinutes(5); private readonly FileInfo file; private long lastFileSize = 0; private DateTime timeOfLastFileSizeIncrease = DateTime.Now; private FileAccessWatcher(string filePath) { this.file = new FileInfo(filePath); } private Task StartWatching() { return Task.Factory.StartNew(this.RunLoop); } private void RunLoop() { while (this.IsFileLocked()) { long currentFileSize = this.GetFileSize(); if (currentFileSize > this.lastFileSize) { this.lastFileSize = currentFileSize; this.timeOfLastFileSizeIncrease = DateTime.Now; } // if the file size has not increased for a pre-defined time limit, cancel if (DateTime.Now - this.timeOfLastFileSizeIncrease > MaximumIdleTime) { break; } } this.RemoveFromWatchedFiles(); this.RaiseFileFinishedCopyingEvent(); } private void RemoveFromWatchedFiles() { FileAccessWatcher accessWatcher; watchedFiles.TryRemove(this.file.FullName, out accessWatcher); } private void RaiseFileFinishedCopyingEvent() { FileFinishedCopying?.Invoke(this, new FileSystemEventArgs(WatcherChangeTypes.Changed, this.file.FullName, this.file.Name)); } private long GetFileSize() { return this.file.Length; } private bool IsFileLocked() { try { using (this.file.Open(FileMode.Open)) { } } catch (IOException e) { var errorCode = Marshal.GetHRForException(e) & ((1 << 16) - 1); return errorCode == 32 || errorCode == 33; } return false; } }

Ejemplo de uso:

// register the event FileAccessWatcher.FileFinishedCopying += FileAccessWatcher_FileFinishedCopying; // start monitoring the file (put this inside the OnChanged event handler of the FileSystemWatcher FileAccessWatcher.RegisterWaitForFileAccess(fileSystemEventArgs.FullPath);

Maneje el FileFinishedCopyingEvent:

private void FileAccessWatcher_FileFinishedCopying(object sender, FileSystemEventArgs e) { Console.WriteLine("File finished copying: " + e.FullPath); }


No hay ninguna función disponible que le permita esperar a que un determinado sistema de control / ubicación del sistema esté disponible para la escritura. Tristemente, todo lo que puedes hacer es sondear el mango para escribir.


Podría usar una declaración de bloqueo con una variable Dummy, y parece funcionar muy bien.

Mira here .


Puede dejar que el sistema espere hasta que se cierre el proceso.

Tan simple como esto:

Process.Start("the path of your text file or exe").WaitForExit();


Si comprueba el acceso antes de escribir en el archivo, es posible que otro proceso le quite el acceso antes de que pueda escribir. Por lo tanto, sugeriría uno de los siguientes dos:

  1. Ajustar lo que desea hacer en un alcance de reintento que no ocultará ningún otro error
  2. Cree un método contenedor que espere hasta que pueda obtener una transmisión y usar esa transmisión

obteniendo una corriente

private FileStream GetWriteStream(string path, int timeoutMs) { var time = Stopwatch.StartNew(); while (time.ElapsedMilliseconds < timeoutMs) { try { return new FileStream(path, FileMode.Create, FileAccess.Write); } catch (IOException e) { // access error if (e.HResult != -2147024864) throw; } } throw new TimeoutException($"Failed to get a write handle to {path} within {timeoutMs}ms."); }

luego úsalo así:

using (var stream = GetWriteStream("path")) { using (var writer = new StreamWriter(stream)) writer.Write("test"); }

reintentar alcance

private void WithRetry(Action action, int timeoutMs = 1000) { var time = Stopwatch.StartNew(); while(time.ElapsedMilliseconds < timeoutMs) { try { action(); return; } catch (IOException e) { // access error if (e.HResult != -2147024864) throw; } } throw new Exception("Failed perform action within allotted time."); }

y luego use WithRetry (() => File.WriteAllText (Path.Combine (_directory, name), contents));


Una función como esta lo hará:

public static bool IsFileReady(string filename) { // If the file can be opened for exclusive access it means that the file // is no longer locked by another process. try { using (FileStream inputStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.None)) return inputStream.Length > 0; } catch (Exception) { return false; } }

Ponlo en un ciclo while y tienes algo que bloqueará hasta que el archivo esté accesible:

public static void WaitForFile(string filename) { //This will lock the execution until the file is ready //TODO: Add some logic to make it async and cancelable while (!IsFileReady(filename)) { } }


Usando la respuesta de @Gordon Thompson, debe crear un bucle como el siguiente:

public static bool IsFileReady(string sFilename) { try { using (FileStream inputStream = File.Open(sFilename, FileMode.Open, FileAccess.Read, FileShare.None)) return inputStream.Length > 0; } catch (Exception) { return false; } } while (!IsFileReady(yourFileName)) ;

Encontré una forma optimizada que no causa pérdidas de memoria:

public static bool IsFileReady(this string sFilename) { try { using (FileStream inputStream = File.Open(sFilename, FileMode.Open, FileAccess.Read, FileShare.None)) return inputStream.Length > 0; } catch (Exception) { return false; } } SpinWait.SpinUntil(yourFileName.IsFileReady);


bool isLocked = true; while (isLocked) try { System.IO.File.Move(filename, filename2); isLocked = false; } catch { } System.IO.File.Move(filename2, filename);