Завершение потока корректно не использование TerminateThread ()

Назад с путаницей.Net 1.1 было важно: декомпиляция кода была легка, и Вы могли пойти от блока, к IL, к коду C# и компилировать его снова с очень небольшим усилием.

Теперь с.Net 3.5 я нисколько не уверен. Попытайтесь декомпилировать 3,5 блока; то, что Вы получаете, является длинным длинным путем от компиляции.

Добавляют оптимизации от 3,5 (намного лучше, чем 1,1) и путь анонимные типы, делегаты и так далее обрабатываются отражением (они - кошмар для перекомпиляции). Добавьте лямбда-выражения, компилятор 'волшебство' как Linq-синтаксис и var, и функции C#2 как yield (который приводит к новым классам с нечитабельными именами). Ваш декомпилируемый код заканчивается длинный длинный путь от компилируемого.

профессионал А подходит к большому количеству времени, мог все еще перепроектировать его назад снова, но тогда то же верно для любого запутываемого кода. Что кодирует, они вышли, который будет неудобен в сопровождении и очень вероятен быть очень ошибочным.

я рекомендовал бы подписанию ключа Ваши блоки (значение, если хакеры могут перекомпилировать тот, они должны перекомпилировать все), но я не думаю путаница, стоящая того.

9
задан Tim Sylvester 9 November 2009 в 18:04
поделиться

3 ответа

TerminateThread - плохая идея, особенно если ваш поток использует объекты синхронизации, такие как мьютексы. Это может привести к неосвобожденной памяти и дескрипторам, а также к взаимоблокировкам, так что вы правы, что вам нужно сделать что-то еще.

Как правило, поток завершается путем возврата из функции, определяющей поток. Основной поток сигнализирует рабочему потоку о выходе, используя объект события или даже простое логическое значение, если оно проверяется достаточно часто. Если рабочий поток ожидает с WaitForSingleObject , вам может потребоваться изменить его на WaitForMultipleObjects , где один из объектов является событием. Основной поток вызовет SetEvent , а рабочий поток проснется и вернется.

Мы действительно не сможем предоставить какой-либо полезный код, если вы не покажете нам, что вы ' повторюсь. В зависимости от того, что делает рабочий поток и как ваш основной поток передает ему информацию, он может выглядеть совсем по-другому.

Кроме того, в [теперь очень старом] MSVC вам нужно вместо этого использовать _beginthreadex of CreateThread во избежание утечек памяти в CRT. См. MSKB # 104641 .

Обновление:

Рабочий поток используется в качестве «таймера» для выполнения некоторых операций через равные промежутки времени. Самое тривиальное:

for (;;) {
    switch (WaitForSingleObject(kill_event, timeout)) {
        case WAIT_TIMEOUT: /*do timer action*/ break;
        default: return 0; /* exit the thread */
    }
}

Другое использование - делать что-то по запросу. В основном то же самое, но с таймаутом INFINITE и выполнением некоторых действий с WAIT_OBJECT_0 вместо WAIT_TIMEOUT . В этом случае вам понадобятся два события: одно для пробуждения потока и выполнения какого-либо действия, другое для его пробуждения и выхода:

HANDLE handles[2] = { action_handle, quit_handle };
for (;;) {
    switch (WaitForMultipleObject(handles, 2, FALSE, INFINITE)) {
        case WAIT_OBJECT_0 + 0: /* do action */ break;
        default:
        case WAIT_OBJECT_0 + 1: /* quit */ break;
    }
}

Обратите внимание, что это ' Важно, чтобы цикл делал что-то разумное, если WFSO / WFMO возвращает ошибку вместо одного из ожидаемых результатов. В обоих приведенных выше примерах мы просто обрабатываем ошибку, как если бы нам был подан сигнал о выходе.

Вы можете достичь того же результата в первом примере, закрыв дескриптор события из основного потока, в результате чего рабочий поток получит ошибку из WaitForSingleObject и выйти, но я бы не рекомендовал такой подход.

19
ответ дан 4 December 2019 в 10:32
поделиться

Что вы делаете в фоновой ветке? Если вы что-то зацикливаете, вы можете завершить поток внутри себя, имея общий общедоступный статический объект (например, Boolean ), который вы установили в true из потока переднего плана и что фоновый поток проверяет наличие и завершает работу, если установлено значение true .

0
ответ дан 4 December 2019 в 10:32
поделиться

Поскольку вы не знаете, что делает поток, нет никакого способа безопасно завершить поток извне.

Как вы думаете, почему вы не можете положить этому конец изнутри?

Вы можете создать событие до запуска потока и передать ему дескриптор этого события. Вы вызываете SetEvent () для этого события из основного потока, чтобы сигнализировать потоку об остановке, а затем WaitForSingleObject для дескриптора потока, чтобы дождаться фактического завершения потока. Внутри цикла потоков вы вызываете WaitForSingleObject () для события, указывая тайм-аут 0 (ноль), так что вызов возвращается немедленно, даже если событие не установлено. Если этот вызов возвращает WAIT_TIMEOUT , событие не устанавливается, если оно возвращает WAIT_OBJECT_0 , установлено. В последнем случае вы возвращаетесь из функции потока.

Я полагаю, ваш поток не просто записывает циклы ЦП в бесконечном цикле, но и выполняет некоторое ожидание, возможно, посредством вызова Sleep () . Если это так, вы можете вместо этого перейти в режим сна в WaitForSingleObject , передав ему тайм-аут.

1
ответ дан 4 December 2019 в 10:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: