2016-05-29 35 views
-3

下面的這個函數假裝擴展Thread.Sleep()函數(或Win32 Sleep/SleepEx),它隻影響調用線程。給定一個線程的id或句柄,我如何確定線程的狀態?

在我的suspendFunc lambda我想確保線程是否真的掛起,然後致電Thread.Sleep(TimeSpan)

我一直在尋找related Win32 thread functions從一個線程處理,線程ID檢索線程的狀態,但我並沒有發現類似的話,無論是我無法找到定義線程狀態的結構或枚舉(只managed one)所以我沒有找到任何提示開始做。

我該怎麼做到這一點?


(注:P /調用不共享代碼的形式提供,我認爲他們沒有必要了解,僅會增加代碼大小。)

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

我猜測線程的.NET實現跟蹤這些信息本身。更大的問題是爲什麼你要重新實現Thread.Sleep。對於初學者來說,這個功能的使用是一個設計不佳的程序的標誌。當然不是對另一個線程有意義的東西,這是你不擁有的東西。如果你想暫停這樣一個線程,調用'SuspendThread'函數。但是,真的,不要這樣做,因爲除非你正在編寫調試器,否則暫停一個線程是一個壞主意。否則,死鎖的城市。 –

+0

暫停非擁有的線程並不意味着設計不良的程序,它在很多場景中都是非常有用,最好且唯一的方法,一個簡單的例子:如果您使用的是第三方命令行工具一個很長的任務(比如說FFMPEG,一個視頻轉換工具),並且你將它們的功能包裝在一個基於.NET的GUI中,然後你想在你的GUI中添加Pause/Resume功能,如果不需要SuspendThread/ResumeThread,你會與外部應用程序的線程互動來做這樣的事情嗎?你看,這很有道理。感謝評論! – ElektroStudios

+4

聽起來不錯,但它是一個等待發生的史詩故障。如果這個長期任務是多線程的呢?你不能只掛起一個線程。是的,我想你可以暫停*全部* FFMPEG線程,但是你又回到了使用SuspendThread。不需要編寫所有這些代碼,也不需要這個問題。 –

回答

3

這是我能得到的最接近的。

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