InvalidOperationException: el objeto está actualmente en uso en otra parte

He pasado por esta pregunta SO, pero no ayudó.

El caso aquí es diferente. Estoy usando Backgroundworkers. 1st backgroundworker comienza a funcionar en la entrada de imagen del usuario y dentro de firstbackgroundworker_runworkercompleted () Estoy usando llamar a otros 3 trabajadores de fondo

algo1backgroundworker.RunWorkerAsync(); algo2backgroundworker.RunWorkerAsync(); algo3backgroundworker.RunWorkerAsync(); 

este es el código para cada uno:

 algo1backgroundworker_DoWork() { Image img = this.picturebox.Image; imgclone = img.clone(); //operate on imgclone and output it } algo2backgroundworker_DoWork() { Image img = this.picturebox.Image; imgclone = img.clone(); //operate on imgclone and output it } 

operaciones similares se realizan en otro algo * backgrougrondworker_doWork ().

Ahora a veces recibo “InvalidOperationException: el objeto está actualmente en uso en otro lado”. Es muy arbitrario. A veces obtengo esto en algo1backgroundworker_DoWork y algunas veces en algo2backgroundworker_DoWork y algunas veces en Application.Run (new myWindowsForm ());

No tengo ni idea de lo que está pasando.

Hay un locking dentro de GDI + que impide que dos subprocesos accedan a un bitmap al mismo tiempo. Este no es un tipo de locking de locking, es un tipo de locking “el progtwigdor hizo algo mal, yo lanzaré una excepción”. Tus hilos están bombardeando porque estás clonando la imagen (== accediendo a un bitmap) en todos los hilos. Su hilo de interfaz de usuario está bombardeando porque está tratando de dibujar el bitmap (== accediendo a un bitmap) al mismo tiempo que un hilo lo está clonando.

Deberá restringir el acceso al bitmap a solo un hilo. Clone las imágenes en el subproceso de la interfaz de usuario antes de iniciar el BGW, cada BGW necesita su propia copia de la imagen. Actualice la propiedad Imagen de PB en el evento RunWorkerCompleted. Perderá algo de concurrencia de esta manera, pero eso es inevitable.

Parece que sus BackgroundWorkers están intentando acceder a los mismos componentes de Windows Forms al mismo tiempo. Esto explicaría por qué la falla es aleatoria.

Deberás asegurarte de que esto no ocurra usando un lock , tal como se ve a continuación:

  private object lockObject = new object(); algo1backgroundworker_DoWork() { Image imgclone; lock (lockObject) { Image img = this.picturebox.Image; imgclone = img.clone(); } //operate on imgclone and output it } 

Tenga en cuenta que me aseguro de que imgclone sea local para este método: definitivamente no desea compartirlo en todos los métodos.

Por otro lado, la misma instancia de lockObject es utilizada por todos los métodos. Cuando un método BackgroundWorker ingresa a la sección de lock{} , otros que lleguen a ese punto serán bloqueados. Por lo tanto, es importante asegurarse de que el código en la sección bloqueada sea rápido.

Cuando llegue a la “salida” de su imagen procesada, tenga cuidado también para asegurarse de que no realice una actualización cruzada de la interfaz de usuario. Revisa esta publicación por una buena manera de evitar eso.

En los formularios de Windows, no solo debe acceder a los controles desde un único subproceso, sino que ese subproceso debe ser el subproceso principal de la aplicación, el subproceso que creó el control.

Esto significa que en DoWork no deberías acceder a ningún control (sin usar Control.Invoke). Entonces aquí llamarías a RunWorkerAsync pasando tu clon de imagen. Dentro del controlador de eventos DoWork, puede extraer el parámetro del DoWorkEventArgs.Argument.

Solo los controladores de eventos ProgressChanged y RunWorkerCompleted deben interactuar con la GUI.