Как я могу наложить свой тайм-аут? - PullRequest
0 голосов
/ 10 февраля 2009

Я должен использовать API, чтобы позвонить третьей стороне, и в идеале использовать ответ, который он возвращает. API имеет встроенный тайм-аут на 30 секунд и не позволяет устанавливать его программно. Мне нужно, чтобы тайм-аут в 12 секунд. Вот звонок, который я делаю:

строковый ответ = theAPI.FunctionA (a, b, c, d);

Я думал, что мне может понадобиться использовать асинхронные вызовы, чтобы выполнить это и прервать поток через 12 секунд. Другой вопрос о стекопереработке, похоже, приближается к тому, что я рассматриваю: Реализация общего тайм-аута C #

... Мне просто интересно, если это лучший способ. В частности, я продолжаю видеть статьи, которые предупреждают вас о необходимости вызова EndInvoke несмотря ни на что, и мне интересно, будет ли Abort, как в приведенном примере, по-прежнему соответствующим образом закрывать поток? Я вижу, что были некоторые комментарии с большим беспокойством об использовании Abort.

Ответы [ 2 ]

4 голосов
/ 10 февраля 2009

Прекращение потоков - вообще плохая идея. Почему бы просто не дать вызову завершиться (или отключиться через 30 секунд), а проигнорировать результат (и двигаться дальше), если это займет более 12 секунд?

2 голосов
/ 10 февраля 2009
Конечно,

Thread.Abort закроет поток, так как он вызовет Win32 TerminateThread.

Результат этого действия будет зависеть от того, как ваш API любит быть закрытым TerminateThread.

Если ваш метод называется что-то вроде NuclearPlant.MoveRod() или Defibrillator.Shock(), я бы лучше подождал эти 30 секунд.

Этот метод не дает пострадавшему возможности провести некоторую очистку:

TerminateThread используется для выхода из потока. Когда это происходит, целевой поток не имеет возможности выполнить какой-либо код режима пользователя . DLL, прикрепленные к потоку, не уведомляются о том, что поток завершается. Система освобождает начальный стек потока.

Как указано в MSDN:

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

  • Если целевой поток владеет критическим разделом, критический раздел не будет освобожден.
  • Если целевой поток выделяет память из кучи, блокировка кучи не снимается.
  • Если целевой поток выполняет определенные вызовы kernel32 после его завершения, состояние kernel32 для процесса потока может быть непоследовательным.
  • Если целевой поток манипулирует глобальным состоянием общей библиотеки DLL, состояние библиотеки DLL может быть уничтожено, что повлияет на других пользователей библиотеки DLL.
...