2016-05-29 3 views
-3

Diese Funktion unten gibt vor, die Thread.Sleep()-Funktion (oder Win32 Sleep/SleepEx) zu erweitern, die nur auf den aufrufenden Thread wirkt.Wie lautet die ID oder der Handle eines Threads, wie kann ich den Status des Threads ermitteln?

In meinem suspendFunc Lambda möchte ich sicherstellen, ob der Thread wirklich gesperrt ist, bevor er Thread.Sleep(TimeSpan) aufruft.

Ich habe gesucht related Win32 thread functions des Threads Zustand von einem Thread-Handle oder Thread-ID abzurufen, aber ich habe nichts Vergleichbares gefunden, weder ich kann keine Struktur oder Aufzählung finden, die die Staaten Thread definiert (nur die managed one) so habe ich keinen Hinweis gefunden, damit anzufangen.

Wie könnte ich das tun ?.


(Hinweis: P/Invokes sind nicht im gemeinsamen Code geliefert, ich denke, dass sie nicht notwendig sind, zu verstehen und verwenden nur die Codegröße erhöhen.)

C#:

public static void SleepThread(int threadId, TimeSpan timespan) 
{ 
    IntPtr hThread = default(IntPtr); 
    int win32Err = 0; 

    // Returns the previous suspend count for the thread. 
    Func<int> suspendFunc =() => 
    { 
     int suspendCount = 0; 
     Debug.WriteLine("Sleeping..."); 
     Thread.Sleep(timespan); 
     Debug.WriteLine("Resuming thread..."); 
     suspendCount = ResumeThread(hThread); 
     CloseHandle(hThread); 
     return suspendCount; 
    }; 

    hThread = OpenThread(ThreadAccessRights.SuspendResume | ThreadAccessRights.Terminate, true, threadId); 
    win32Err = Marshal.GetLastWin32Error(); 

    if ((hThread == IntPtr.Zero)) { 
     throw new Win32Exception(win32Err); 

    } else { 
     Debug.WriteLine("Pausing thread..."); 
     Task<int> suspendTask = Task.Factory.StartNew<int>(suspendFunc); 
     SuspendThread64(hThread); 

    } 

} 

//======================================================= 
//Service provided by Telerik (www.telerik.com) 
//======================================================= 

VB.NET:

Public Shared Sub SleepThread(ByVal threadId As Integer, ByVal timespan As TimeSpan) 

    Dim hThread As IntPtr 
    Dim win32Err As Integer 

    Dim suspendFunc As Func(Of Integer) = 
     Function() As Integer ' Returns the previous suspend count for the thread. 
      Dim suspendCount As Integer 
      Debug.WriteLine("Sleeping...") 
      Thread.Sleep(timespan) 
      Debug.WriteLine("Resuming thread...") 
      suspendCount = ResumeThread(hThread) 
      CloseHandle(hThread) 
      Return suspendCount 
     End Function 

    hThread = OpenThread(ThreadAccessRights.SuspendResume Or ThreadAccessRights.Terminate, True, threadId) 
    win32Err = Marshal.GetLastWin32Error() 

    If (hThread = IntPtr.Zero) Then 
     Throw New Win32Exception(win32Err) 

    Else 
     Debug.WriteLine("Pausing thread...") 
     Dim suspendTask As Task(Of Integer) = Task.Factory.StartNew(Of Integer)(suspendFunc) 
     SuspendThread64(hThread) 

    End If 

End Sub 
+2

Ich vermute, dass die .NET-Implementierung von Threads diese Informationen selbst verfolgt. Die größere Frage ist, warum Sie Thread.Sleep erneut implementieren. Für den Anfang ist die Verwendung dieser Funktion ein Zeichen für ein schlecht konzipiertes Programm. Und sicherlich nicht etwas, das Sinn macht für einen anderen Thread, den du nicht besitzt. Wenn Sie einen solchen Thread aussetzen möchten, rufen Sie die Funktion 'SuspendThread' auf. Aber wirklich, nicht, denn einen Thread zu suspendieren ist eine schlechte Idee, es sei denn, Sie schreiben einen Debugger. Sonst, Deadlock-Stadt. –

+0

Das Aussetzen eines nicht im Besitz befindlichen Threads muss kein schlecht konzipiertes Programm sein, es ist sehr hilfreich, am besten und nur in vielen Szenarien, ein einfaches Beispiel: Wenn Sie ein Befehlszeilentool eines Drittanbieters verwenden eine lange Aufgabe (sagen wir FFMPEG, ein Video-Konverter-Tool) und dass Sie ihre Funktionalitäten in eine .NET-basierte GUI verpackt haben, und Sie dann Pause/Resume-Funktionen in Ihrer GUI hinzufügen möchten, ist SuspendThread/ResumeThread erforderlich, wenn nicht, wie Sie werden mit dem Thread der externen App interagieren, um so etwas zu tun? Siehst du, es ergibt Sinn. Danke für den Kommentar! – ElektroStudios

+4

Es klingt gut, aber es ist ein epischer Fehler, der darauf wartet, zu passieren. Was ist, wenn diese lange Aufgabe Multi-Threading ist? Sie können nicht einfach einen Thread aussetzen. Und ja, ich denke du könntest * alle * FFMPEG-Threads aussetzen, aber dann bist du wieder bei SuspendThread. Es ist nicht nötig, den gesamten Code zu schreiben und diese Frage nicht zu stellen. –

Antwort

3

Das ist das nächste, was ich bekommen kann.

Function GetThreadState(ProcId As Integer, ThreadId As Integer) As Threading.ThreadState 
    For Each Thr As Threading.Thread In Process.GetProcessById(ProcId).Threads 
     If Thr.ManagedThreadId = ThreadId Then Return Thr.ThreadState 
    Next 
    Throw New ArgumentOutOfRangeException("Thread not found.") 
End Function 
Verwandte Themen