2010-04-23 14 views
7

Ho un thread gestito che è in attesa, bloccato, in un codice non gestito (in particolare, su una chiamata a NamedPipeServerStream.WaitForConnection() che chiama in modo superfluo nel codice non gestito e fa non offre un timeout).Come terminare un thread gestito bloccato nel codice non gestito?

Voglio chiudere il thread in modo ordinato.

Thread.Abort() non ha alcun effetto fino a quando il codice non ritorna al dominio gestito, che non eseguirà finché un client non effettua una connessione, che non possiamo attendere).

Ho bisogno di un modo per "scioccarlo" dal codice non gestito; o un modo per uccidere il filo anche mentre si trova in una terra non gestita.

+1

Qualsiasi motivo per cui non stai utilizzando NamedPipeServerStream.BeginWaitForConnection()? – SpaceghostAli

+1

Fondamentalmente perché il thread vuole aspettare "per sempre" per una connessione (a meno che non si arresti). Con Begin/End WaitForConnection, dovrei iniziare, attendere un secondo, verificare la connessione o il timeout e interrompere il timeout. –

+1

Ok ho capito. Beh, una leggera modifica alla risposta di dtb dovrebbe darti quello che ti serve. Invece di aspettare su asyncResult, aspetta su un WaitHandle condiviso che imposti dal codice che vuole interrompere il thread. – SpaceghostAli

risposta

19

Hai provato a utilizzare il metodo non bloccante NamedPipeServerStream.BeginWaitForConnection?

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

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

Non devono necessariamente utilizzare un timeout fisso. È possibile utilizzare un ManualResetEvent per segnalare quando il filo deve smettere di aspettare per il collegamento:

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

Il segnale deve anche essere impostato all'interno di un callback passato a BeginWaitForConnection. Quindi l'esempio sarà completo. –

1

Non v'è alcun modo per "ordinatamente" arrestare un filo dall'esterno, se quel filo è in esecuzione il codice unmannaged. Ci sono un paio di modi per interrompere bruscamente il thread, ma probabilmente non è quello che vuoi.

Utilizzare invece BeginWaitForConnection.

0

In realtà, la soluzione che ho usato (che mi è venuto in mente mentre stavo scrivendo la domanda), era, dopo aver interrotto tutti i thread, solo per creare (e disporre immediatamente) un client per ogni thread.

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

Con la connessione, restituisce al codice gestito, e l'interruzione() calci (il filo catture ThreadAbortException e si pulisce)

Questo non funziona per il caso generale (cioè, la domanda posta nel titolo), ma funziona per me ...

+0

Se segui questo schema pazzo, assicurati di utilizzare un timeout appropriato su Connect, nel caso in cui un altro processo stabilisca una connessione solo nel momento sbagliato, causando l'interruzione del thread di ascolto e il blocco di questo thread! –

Problemi correlati