2011-12-22 2 views
2

Я пытаюсь прекратить ЮНА вызов WaitForSignleObject() с Timer, который прерывает текущий поток:таймер Java не работает при использовании ЮНА вызов Win32 WaitForSingleObject()

final Thread thread = Thread.currentThread(); 
Timer timer = new Timer(); 
timer.schedule(new TimerTask() { 
    public void run() { 
    thread.interrupt(); 
    } 
}, 3000); 

try {    
    Kernel32.INSTANCE.WaitForSingleObject(processInfo.hProcess, Kernel32.INFINITE); 
    ... 
} catch (InterruptedException e) { 
} 

Проблема заключается в том, что TimerTask.run() является не вызывается через 3 секунды, как и ожидалось, вызывается только после того, как WaitForSingleObject() выходит из себя. Что я делаю не так?

Спасибо!

+0

Вы уверены, что 'run()' не вызывается, или просто 'InterruptedException' не выбрасывает? – axtavt

+0

Да, я проверил, что с точкой останова put in run() – spektom

+0

Это довольно странно, вы пытались проверить его другими способами? – axtavt

ответ

2

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

Если вам нужен только тайм-аут, вы можете использовать второй аргумент WaitForSingleObject(). Если вам нужна более сложная логика, вы можете create an event уведомить ожидающий поток о прерывании и использовать WaitForMultipleObjects() на этом мероприятии и ваш hProcess.

+0

You вероятно, хочет использовать любой механизм, который Windows предоставляет для вызова метода WaitForXXX (в зависимости от объекта mutex, например «TerminateProcess» для использования с hProcess в вопросе). – technomage

0

При взгляде на документацию Microsoft для WaitForSingleObject есть предположение, что вы можете подумать о WaitForSingleObjectEx вместо этого (чтобы ввести «аварийное состояние ожидания»).

+0

Обходной путь для передачи значения таймаута в WaitForSingleObjectEx(), и я не хотел его использовать в первую очередь, так как он ломает мой API :) (я завершаю обработку обработчика окон в java.lang.Process) – spektom

0

Проблема заключается в том, что TimerTask.run() не вызывается после 3 секунд прошло, как и ожидалось, это называется только после WaitForSingleObject() выходит сам. Что я делаю не так?

Простой ответ: вы делаете блокирующий вызов в операционной системе. Пока ваш поток заблокирован, TimerTask в этом потоке не будет срабатывать.

Даже если вы запустили TimerTask в другом потоке, маловероятно, что прерывание будет работать, так как Thread.interrupt является специфичной для Java функцией (как указывал @axtavt).

Если вам нужна дополнительная помощь, пожалуйста, создайте другое сообщение и объясните, зачем вам это нужно и каковы ваши ограничения (что-то более конкретное, чем «... он ломает мой API»). Возможно, мы найдем альтернативный подход.

+0

Таймер будет выполнять свои задачи в потоке, отличном от текущего (т. Е. Потоке, который блокируется). Не существует очевидной причины, по которой она не будет срабатывать (и не ударить точку останова, установленную в «run», не является гарантией того, что она не выполнялась * не *). Однако нативная функция никоим образом не обязана делать * ничего * в ответ на прерывание потока Java. – technomage

+0

Если это так, то простой ответ заключается в том, что вы пытаетесь прервать неправильный поток: код говорит 'Thread.currentThread(). Interrupt()', но вызов API находится в другом потоке. – jdigital

+0

@jdigital, см. Мое редактирование, я исправил код. Первоначально код был верным, и он вызывал прерывание() в правильном потоке. – spektom

1

Довольно много ошибок в этом простом коде;

  • В течение run() код прерывает текущий поток вызовов - бесполезно, вы хотите, чтобы поток выполнял собственный вызов.
  • Вам необходимо обработать прерывание собственного вызова.

Ниже ссылка на способ правильной обработки со стороны java. Detecting thread interruption with JNA native wait call (Windows)

Со стороны WinAPI: в зависимости от вашего случая вам может потребоваться CloseHandle, SetEvent или любое другое уведомление, которое вам нужно. Затем, вернувшись из WaitForSingleObject, проверьте состояние объекта и перетащите InterruptedException, если вам нужно.

+0

Извините, я написал код прямо здесь и не обратил внимания на то, что неверный поток прерывается. Первоначально код выглядит более похожим на это после редактирования, которое я сделал. – spektom

+0

Я пытался использовать 'AbstractInterruptibleChannel', но это не помогает в моем случае, так как поток все равно не прерывается. Этот абстрактный класс может быть полезен для очистки ресурсов системы при прерывании потока, но я не могу сделать это прерывание. – spektom

+0

Право! AIC может помочь обработать прерывание() из java и передать собственный вызов, т. Е. Придерживаться Java API. Конечно, он ничего не делает сам по себе. Вы должны следовать за второй частью в WinAPI, либо закрыть дескриптор процесса через 'TerminateProcess (handle, exitCode)', если это внешний процесс, который ожидает поток, или сделать все, что требуется для выхода из WaitForSingleObject. В любом случае вам нужно использовать функцию WinAPI, чтобы освободить ожидающий поток. Java не может справиться с задачей только через Thread.interrupt. Прошло более десяти лет, когда я сделал код WinAPI, но если вы разместите еще какой-нибудь код, я могу помочь. – bestsss

Смежные вопросы