usar try tipos que existen excepciones errores ejemplos definicion como catch capturar c# multithreading exception

tipos - try catch c# messagebox



¿Hay un buen método en C#para arrojar una excepción en un hilo dado? (8)

El código que quiero escribir es así:

void MethodOnThreadA() { for (;;) { // Do stuff if (ErrorConditionMet) ThrowOnThread(threadB, new MyException(...)); } } void MethodOnThreadB() { try { for (;;) { // Do stuff } } catch (MyException ex) { // Do the right thing for this exception. } }

Sé que puedo hacer que el hilo B se revise periódicamente, de forma segura, para ver si el hilo A ha establecido un indicador, pero eso hace que el código sea más complicado. ¿Hay algún mecanismo mejor que pueda usar?

Aquí hay un ejemplo más realzado de comprobación periódica:

Dictionary<Thread, Exception> exceptionDictionary = new Dictionary<Thread, Exception>(); void ThrowOnThread(Thread thread, Exception ex) { // the exception passed in is going to be handed off to another thread, // so it needs to be thread safe. lock (exceptionDictionary) { exceptionDictionary[thread] = ex; } } void ExceptionCheck() { lock (exceptionDictionary) { Exception ex; if (exceptionDictionary.TryGetValue(Thread.CurrentThread, out ex)) throw ex; } } void MethodOnThreadA() { for (;;) { // Do stuff if (ErrorConditionMet) ThrowOnThread(threadB, new MyException(...)); } } void MethodOnThreadB() { try { for (;;) { // Do stuff ExceptionCheck(); } } catch (MyException ex) { // Do the right thing for this exception. } }


@Orion Edwards

Considero tu punto sobre una excepción lanzada en el bloque final.

Sin embargo, creo que hay una manera, usando otro hilo, de usar esta idea de excepción como interrupción.

Tema A:

At some random time, throw an exception on thread C:

Hilo B:

try { Signal thread C that exceptions may be thrown //do stuff, without needing to check exit conditions Signal thread C that exceptions may no longer be thrown } catch { // exception/interrupt occurred handle... } finally { // ...and clean up CloseResourceOne(); CloseResourceTwo(); }

Hilo C:

while(thread-B-wants-exceptions) { try { Thread.Sleep(1) } catch { // exception was thrown... if Thread B still wants to handle exceptions throw-in-B } }

¿O es eso tonto?


Al igual que los demás, no estoy seguro de que sea una buena idea, pero si realmente quieres hacerlo, puedes crear una subclase de SynchronizationContext que permita publicar y enviar delegados al hilo de destino (si es un hilo de WinForms el trabajo está hecho para ti, ya que tal subclase ya existe). Sin embargo, el hilo de destino deberá implementar algún tipo de bomba de mensaje equivalente para recibir a los delegados.


Esta NO es una buena idea

Este artículo habla sobre la biblioteca de tiempo de espera de ruby. que arroja excepciones entre los hilos.

Explica cómo hacer algo así se rompe fundamentalmente. No solo está roto en rubí, está roto en cualquier lugar que arroje excepciones entre los hilos.

En pocas palabras, lo que puede suceder (y sucede) es esto:

ThreadA:

At some random time, throw an exception on thread B:

ThreadB:

try { //do stuff } finally { CloseResourceOne(); // ThreadA''s exception gets thrown NOW, in the middle // of our finally block and resource two NEVER gets closed. // Obviously this is BAD, and the only way to stop is to NOT throw // exceptions across threads CloseResourceTwo(); }

Su ejemplo de "comprobación periódica" está bien, ya que no está lanzando excepciones entre los hilos.
Solo estás configurando una bandera que dice "lanzar una excepción la próxima vez que mires esta bandera", lo cual está bien ya que no sufre el problema "se puede lanzar en el medio de tu captura o finalmente bloquear".
Sin embargo, si va a hacer eso, también puede ser que esté configurando un indicador de "salir ahora" y usarlo y ahorrarse la molestia de crear el objeto de excepción. Un bool volátil funcionará bien para eso.


Existen suficientes problemas con las excepciones que otros mecanismos pueden lanzar en los hilos, como el aborto de hilos y "me gusta", para que pueda encontrar otra forma de hacerlo.

Una excepción es un mecanismo utilizado para indicar que un proceso ha experimentado algo excepcional que no puede resolver. Debería tratar de evitar escribir el código para que se use una excepción para indicar que algo más ha experimentado algo excepcional.

Es probable que ese otro hilo no sepa cómo manejar la excepción en todos los casos en que el código pueda arrojarla .

En resumen, debe encontrar algún otro mecanismo para abortar sus hilos que usar excepciones.

Use objetos de evento o similares para decirle a un hilo que aborte su procesamiento, esa es la mejor manera.


Lo que Orion Edwards está diciendo no es del todo cierto: no es la "única" manera.

// Obviously this is BAD, and the only way to stop is to NOT throw // exceptions across threads

El uso de CER ( regiones de ejecución restringida ) en C # le permite liberar sus recursos como una operación atómica, protegiendo su código de las excepciones entre hilos. Esta técnica es utilizada por varias clases de .NET Framework que funcionan con la API nativa de Windows, donde un identificador inédito puede causar una pérdida de memoria.

Consulte http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.runtimehelpers.prepareconstrainedregions.aspx

El siguiente ejemplo muestra cómo establecer confiablemente identificadores usando el método PrepareConstrainedRegions . Para establecer de forma confiable un identificador a un identificador preexistente especificado, debe asegurarse de que la asignación del identificador nativo y la posterior grabación de ese identificador dentro de un objeto SafeHandle sea ​​atómica. Cualquier falla entre estas operaciones (como un aborto de un hilo o una excepción de falta de memoria) dará como resultado el escape del identificador nativo. Puede usar el método PrepareConstrainedRegions para asegurarse de que el identificador no se haya filtrado.

Tan simple como:

public MySafeHandle AllocateHandle() { // Allocate SafeHandle first to avoid failure later. MySafeHandle sh = new MySafeHandle(); RuntimeHelpers.PrepareConstrainedRegions(); try { } finally // this finally block is atomic an uninterruptible by inter-thread exceptions { MyStruct myStruct = new MyStruct(); NativeAllocateHandle(ref myStruct); sh.SetHandle(myStruct.m_outputHandle); } return sh; }


Me interesa saber por qué querrías hacer esto. No hay una manera fácil de hacerlo, porque no es una buena práctica. Probablemente debería volver a su diseño y descubrir una forma más limpia de lograr el objetivo final.



No creo que sea una buena idea. Analicemos otra vez este problema: intente utilizar algún otro mecanismo, como datos compartidos, para señalar entre hilos.