2010-04-23 19 views
7

Tengo un hilo administrado que está esperando, bloqueado, en un código no administrado (específicamente, en una llamada a NamedPipeServerStream.WaitForConnection() que finalmente llama al código no administrado, y no ofrecen un tiempo de espera).¿Cómo finalizar un hilo gestionado bloqueado en código no administrado?

Quiero cerrar el hilo cuidadosamente.

Thread.Abort() no tiene efecto hasta que el código regrese al dominio administrado, lo que no ocurrirá hasta que un cliente haga una conexión, lo cual no podemos esperar.

Necesito una forma de "sacudirlo" del código no administrado; o una forma de simplemente matar el hilo, incluso mientras está en tierra no administrada.

+1

¿Alguna razón por la que no está usando NamedPipeServerStream.BeginWaitForConnection() en su lugar? – SpaceghostAli

+1

Básicamente porque el hilo desea esperar "para siempre" para una conexión (a menos que se cierre). Con Begin/End WaitForConnection, tendría que comenzar, esperar un segundo, verificar la conexión o el tiempo de espera, y repetir el tiempo de espera. –

+1

Ok, lo entiendo. Bueno, una pequeña modificación a la respuesta de dtb debería darle lo que necesita. En lugar de esperar en asyncResult, espere en un WaitHandle compartido que configure desde el código que desea abortar el hilo. – SpaceghostAli

Respuesta

19

¿Ha intentado utilizar el método NamedPipeServerStream.BeginWaitForConnection sin bloqueo?

using (NamedPipeServerStream stream = ...) 
{ 
    var asyncResult = stream.BeginWaitForConnection(null, null); 

    if (asyncResult.AsyncWaitHandle.WaitOne(5000)) 
    { 
     stream.EndWaitForConnection(asyncResult); 
     // success 
    } 
} 

No tiene que utilizar necesariamente un tiempo de espera fijo. Puede utilizar un ManualResetEvent para señalar cuando el hilo debe dejar de esperar que la conexión:

ManualResetEvent signal = new ManualResetEvent(false); 

using (NamedPipeServerStream stream = ...) 
{ 
    var asyncResult = stream.BeginWaitForConnection(_ => signal.Set(), null); 

    signal.WaitOne(); 
    if (asyncResult.IsCompleted) 
    { 
     stream.EndWaitForConnection(asyncResult); 
     // success 
    } 
} 

// in other thread 
void cancel_Click(object sender, EventArgs e) 
{ 
    signal.Set(); 
} 
+0

La señal también debe establecerse dentro de una devolución de llamada pasada a BeginWaitForConnection. Entonces el ejemplo estará completo. –

1

No hay manera de "limpiamente" cerrar un hilo desde el exterior, en caso de que el hilo se está ejecutando código unmannaged. Hay un par de maneras de terminar abruptamente el hilo, pero probablemente eso no sea lo que quieres.

En su lugar, debe usar BeginWaitForConnection.

0

En realidad, la solución que utilicé (que se me ocurrió mientras escribía la pregunta) fue, después de abortar todos los hilos, crear (y disponer inmediatamente) un cliente para cada hilo.

threads.ForEach(thread=> thread.Abort()); 
    threads.ForEach(thread=> 
       { 
        var client = new PipeClient(ServiceName); 
        client.Connect(); 
        client.Dispose(); 
       }); 

Con la conexión, vuelve a código administrado, y el Abortar() entra en acción (el hilo atrapa ThreadAbortException y se limpia a sí misma)

esto no funciona para el caso general (es decir, la pregunta planteada en el título), pero funciona para mí ...

+0

Si te vas con este esquema loco, asegúrate de utilizar un tiempo de espera apropiado en Connect, solo en caso de que otro proceso establezca una conexión en el momento incorrecto, provocando que el hilo de escucha se cierre y este hilo se bloquee. –

Cuestiones relacionadas