Эта функция ниже претендует на расширение функции Thread.Sleep()
(или Win32 Sleep
/SleepEx
), которая влияет только на вызывающий поток.Учитывая идентификатор потока или дескриптор потока, как я могу определить состояние потока?
В моем suspendFunc
лямбда Я хотел бы убедиться, что поток действительно приостановлен, прежде чем звонить Thread.Sleep(TimeSpan)
.
Я искал related Win32 thread functions получить состояние потока от ручки потока или идентификатор потока, но я не нашел ничего подобного, ни я не могу найти структуру или перечисление, который определяет нить состояния (только 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
Я предполагаю, что реализация потоков в .NET отслеживает эту информацию. Чем больше вопрос, почему вы повторно реализуете Thread.Sleep. Во-первых, само использование этой функции является признаком плохо разработанной программы. И, конечно, не что-то, что имеет смысл для * другой * нити, той, которой вы не владеете. Если вы хотите приостановить такой поток, вызовите функцию 'SuspendThread'. Но на самом деле, не надо, потому что приостановленный поток - плохая идея, если вы не пишете отладчик. В противном случае, тупиковый город. –
Приостановка использования не принадлежащей нити не должна означать плохо разработанную программу, она очень полезна, лучше всего подходит и подходит только во множестве сценариев: один простой пример: если вы используете сторонний инструмент командной строки, который выполняет (скажем, FFMPEG, инструмент видео конвертера), и что вы завернули свои функциональные возможности в графическом интерфейсе на основе .NET, а затем вы хотите добавить функции Pause/Resume в свой графический интерфейс, SuspendThread/ResumeThread требуется, если нет, то как вы будете взаимодействовать с потоком внешнего приложения, чтобы делать такую вещь ?. Понимаете, это имеет смысл. Спасибо за комментарий! – ElektroStudios
Звучит неплохо, но это эпический провал, ожидающий своего появления. Что делать, если эта длинная задача многопоточная? Вы не можете просто приостановить один поток. И да, я думаю, вы могли бы приостановить * все * потоков FFMPEG, но затем вы вернетесь к использованию SuspendThread. Не нужно писать весь этот код, и нет необходимости в этом вопросе. –