2014-07-02 15 views
6

Creazione di un thread in background in C# in modo normale -Come ottenere un handle di thread da passare a CancelSynchronousIO?

Thread t = new Thread(....); 
t.IsBackground = true; 
t.Start(); 
etc etc 

Volendo chiamare CancelSynchronousIO dal thread principale per annullare un blocco di chiamata IO il thread in background. Non sanno come ottenere un handle di thread in forma di IntPtr per passare alla funzione:

[DllImport("kernel32.dll", SetLastError=true)] 
static extern bool CancelSynchronousIo(IntPtr threadHandle); 

Sembra esserci vari modi di ottenere un ID di thread, ma non un manico? E i modi di ottenere un ID thread sembrano darti un ID solo all'interno dell'ambiente gestito, quindi non usare per le chiamate PInvoke? Immagino che mi manchi qualcosa.

Devo eseguire altre chiamate PInvoke per ottenere l'handle del thread o esiste un modo più semplice?

+0

il codice potrebbe essere in esecuzione su un thread gestito, non su un thread nativo. –

+0

vedere: http://msdn.microsoft.com/en-us/library/74169f59(v=vs.110).aspx –

+1

@ DanielA.White: thread gestiti _are_ thread nativi; Le fibre non vengono quasi mai utilizzate. – SLaks

risposta

3

Si può fare, ma è altamente sconsigliato.

using System; 
using System.Diagnostics; 
using System.Runtime.InteropServices; 
using System.Threading; 

class Program 
{ 
    [DllImport("kernel32.dll", SetLastError = true)] 
    static extern uint GetCurrentThreadId(); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    static extern IntPtr OpenThread(uint desiredAccess, bool inheritHandle, uint threadId); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    static extern bool CloseHandle(IntPtr handle); 

    [DllImport("kernel32.dll", SetLastError = true)] 
    static extern bool CancelSynchronousIo(IntPtr threadHandle); 

    static bool CancelSynchronousIo(uint threadId) 
    { 
     // GENERIC_WRITE, Non-inheritable 
     var threadHandle = OpenThread(0x40000000, false, (uint)threadId); 
     var ret = CancelSynchronousIo(threadHandle); 

     CloseHandle(threadHandle); 

     return ret; 
    } 

    static void Main(string[] args) 
    { 
     uint threadId = 0; 

     using (var threadStarted = new AutoResetEvent(false)) 
     { 
      var thread = new Thread(() => 
      { 
       try 
       { 
        Thread.BeginThreadAffinity(); 
        threadId = GetCurrentThreadId(); 

        threadStarted.Set(); 

        // will throws System.OperationCanceledException 
        Console.ReadLine(); 
       } 
       finally 
       { 
        Thread.EndThreadAffinity(); 
       } 
      }); 

      thread.Start(); 

      threadStarted.WaitOne(); 
     } 

     Debugger.Break(); 

     CancelSynchronousIo(threadId); 
    } 
} 
+0

Puoi spiegare o fare riferimento perché non è raccomandato? – jklemmack

Problemi correlati