c# - org - mapwindows 5
¿Por qué PictureBox.Load bloquea la imagen en algunos sistemas? (2)
Sí, esto es normal. Sucede en cualquier sistema operativo, no tiene nada que ver con la ubicación de la carpeta Usuarios. El método PictureBox.Load () estaba destinado a ser utilizado para cargar imágenes desde ubicaciones distintas del sistema de archivos. Como un sitio web Lo cual es lento, evita congelar la IU mientras se realiza la descarga.
Utiliza internamente un FileStream cuando descubre que la url que pasa es en realidad un archivo y no un nombre de sitio web. Este FileStream no se elimina hasta que el propio PictureBox se elimine o vuelva a llamar al método Load (). Un requisito porque Image.FromStream () requiere que la transmisión siga siendo legible hasta que la imagen ya no se use. Es este FileStream que mantiene un bloqueo en el archivo. La eliminación de PictureBox.Image no es suficiente para disponer de FileStream, el objeto Image no sabe que se está mostrando dentro de un cuadro de imagen.
Hay varias formas de resolver este problema:
- Use la propiedad Imagen en lugar de Cargar (), asígnela de Image.FromFile (). La eliminación de la imagen ahora también libera el bloqueo en el archivo. Como descubriste
- Mantenga una imagen ficticia, una que tal vez muestre un mapa de bits "Cargando ...". Cargar () primero para liberar el bloqueo en el archivo
- Elimine el PictureBox y recíclelo.
(Consulte la edición en la parte inferior de la pregunta, si no desea leer toda la historia).
Hola,
Soy nuevo en stackoverflow. No me malinterpreten, lo uso con bastante frecuencia. Pero hasta ahora nunca publiqué algo. Esto es porque no tenía algo nuevo / útil que decir y mi inglés no es tan bueno. Lo primero (podría haber cambiado), lo último no.
Me encontré con un problema en el sistema Windows 7 de un cliente bastante recientemente. Estaba enviando una aplicación de Windows Forms de C # .Net 4.0 a través de ClickOnce. Básicamente, es una aplicación que crea un archivo de mapa de bits y lo muestra al usuario. Si el mapa de bits existe antes de la creación, el archivo existente se elimina primero. Después de eso, el nuevo archivo es creado y cargado por PictureBox.
Ocurrió lo siguiente en el sistema del cliente: después de iniciar la aplicación, la primera creación tiene éxito; la segunda y todas las siguientes no. El archivo no se puede eliminar porque algún proceso lo está bloqueando. Este proceso es la aplicación en sí misma.
System.IO.IOException: el proceso no puede acceder al archivo "nombre de archivo" porque lo está utilizando otro proceso.
Bueno, por supuesto, eso no es nada inusual. El caso es que probé la aplicación en varios sistemas. Ninguno mostró esta excepción. Y hasta ahora no puedo ver un código de error.
Así que miré un poco más de cerca en el sistema del cliente: la única diferencia que pude encontrar es que cambiaron la carpeta de los usuarios para que no se ubicaran en la partición de Windows, sino en una diferente (C: / Users -> D: / Usuarios). Busqué una instrucción en Internet e hice lo mismo en uno de mis sistemas de prueba. Para mi sorpresa, recibí la misma excepción cuando ejecuté mi aplicación en él.
Con eso puedo cambiar mi código para que la excepción ya no ocurra. Pero no entiendo por qué es eso. Entonces, tal vez haya algún problema con mi código y el error simplemente se revela en esas circunstancias especiales. O tal vez el código está bien y la razón se encuentra en otro lado. Solo esperaba que pudieras ayudarme.
Así que aquí hay un código que armé, que muestra el mismo comportamiento. Usé 3 botones, un OpenFileDialog y un PictureBox en un Formulario. Lo primero que debe hacer es elegir un archivo de imagen. Al presionar uno de los dos botones restantes, se copia en la carpeta principal de la aplicación. Después de ser copiado, se muestra en PictureBox. Por cierto, no parece importar si se trata de una aplicación ClickOnce o una "normal".
String m_FileName;
private void btnChooseFile_Click(object sender, EventArgs e) {
if(openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK) { // If file was chosen, set file name for later use and activate buttons.
m_FileName = "Test" + Path.GetExtension(openFileDialog1.FileName);
}
}
private void button1_Click(object sender, EventArgs e) {
// This is not working.
if(this.pictureBox1.Image != null) {
//Image img = this.pictureBox1.Image; // I was not sure, if maybe the pictureBox somehow prevents the disposing of the image, as long as it''s assigned to it.
//this.pictureBox1.ImageLocation = null; // So I set them null, both the image and the image location.
//this.pictureBox1.Image = null;
//img.Dispose(); // Then I disposed the image.
this.pictureBox1.Image.Dispose(); // The short version. It is not working either way.
this.pictureBox1.Image = null;
}
(new FileInfo(openFileDialog1.FileName)).CopyTo(m_FileName, true); // But still this is where the Exception occurs.
this.pictureBox1.Load(m_FileName);
}
private void button2_Click(object sender, EventArgs e) {
//This is working.
if(this.pictureBox1.Image != null) {
//Image img = this.pictureBox1.Image;
//this.pictureBox1.Image = null;
//img.Dispose();
this.pictureBox1.Image.Dispose();
this.pictureBox1.Image = null;
}
(new FileInfo(openFileDialog1.FileName)).CopyTo(m_FileName, true);
pictureBox1.Image = Image.FromFile(m_FileName);
}
Lo que sucede ahora es lo siguiente: si inicio la aplicación y hago clic en el botón 1 dos veces, obtendré la excepción (en el segundo clic). Si lo comienzo y hago clic en el botón 2 dos veces, no lo haré. Si comienzo la aplicación y hago clic en los botones 1 primero y después de ese botón 2, obtendré la excepción. Entonces, la función Picture.Load-de alguna manera bloquea el archivo, incluso si lo desecho.
Cuando busqué en Internet, encontré un artículo de Microsoft: http://support.microsoft.com/kb/309482/en-us . Pero no da en el blanco.
Tenga en cuenta que ambas versiones funcionan en todas mis máquinas de prueba. Acabo de recibir la excepción cuando cambio la carpeta de los usuarios a una partición que no sea de Windows.
¿Porqué es eso? ¿Y dónde está la diferencia en las versiones presentadas?
Editar
Bien, debido a la primera y única reacción hasta ahora, me parece, que todavía no está claro, lo que realmente sucede: si tomo el código anterior, lo pongo en una aplicación de Windows Forms, lo compilo y lo ejecuto en diferentes las computadoras (en el trabajo, en el hogar, no importa) funcionan: tanto el botón1 como el botón2 (con las funciones de clic vinculadas a ellos) se pueden usar tantas veces como me plazca, sin excepciones. Si ejecuto la aplicación en una computadora, donde cambié la carpeta de usuarios, y hago clic en el botón 1 por segunda vez, bam - IOException, archivo bloqueado por proceso. Button2 funciona siempre que no presione el botón1.
La primera respuesta implica que debería obtener el bloqueo en cada sistema. ¡PERO NO (siempre y cuando no cambie la carpeta de los usuarios)! Lo probé en todas las computadoras que pude tener, sin excepción IOException. Configuré un nuevo sistema, solo para descartar algunos cambios especiales en los sistemas de mi empresa: las dos funciones de Buttonx_Click funcionaron, sin excepción. Incluso compilé el programa en otra computadora, el mismo comportamiento. Los únicos tres sistemas para lanzar esa excepción fueron los que tienen la carpeta de usuarios modificada.
Hasta ahora no tengo idea de por qué ocurre esta diferencia en el comportamiento. ¿Puede alguien ayudarme?
¿Nadie?
Ver este enlace En realidad, es un problema con el IDE en Visual Studio.