2012-01-24 2 views
10

Мое консольное приложение выполняет поток, полностью посвященный пользовательскому интерфейсу, он тратит много времени на Console.ReadLine() (этот вызов проводит свое время глубоко в недрах Windows, вне контроля платформы .NET) ,Как прервать другой поток в .NET, когда указанный поток выполняет Console.ReadLine?

Мне нужно отменить эту тему. Однако следующий код не работает:

this.UserInterfaceThread.Abort(); 

Любые идеи? Будет ли Thread.Interrupt() использоваться?

Update

Как Ганс Passant отметил:

Среда CLR устанавливает довольно вменяемые правила о состоянии нити, когда она ликвидирует его. Опасности Thread.Abort() хорошо известны, что, безусловно, никогда не может работать надежно, прерывает поток, который выполняет неуправляемый код. В этом случае, когда вы вызываете Console.ReadLine(), поток зарывается глубоко внутри кода операционной системы Windows.

Решение состоит в том, чтобы просто нажать клавишу [enter] в текущее консольное приложение, которое блокирует Console.ReadLine(), поэтому поток немедленно прерывается.

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

Решение состоит в использовании библиотеки в inputsimulator.codeplex.com, которая завершает вызов Windows SendInput().

См пример кода:

.NET call to send [enter] keystroke into the current process, which is a console app?

+0

Возможный дубликат [Как добавить тайм-аут в Console.ReadLine()?] (Http://stackoverflow.com/questions/57615/how-to-add-a-timeout-to-console-readline) –

+3

'Thread.Abort' [is evil] (http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation). – spender

+0

@ Darin Dimitrov: Это не дубликат. Этот вопрос касается того, как прервать поток, который запускает один экземпляр Console.ReadLine(). – Contango

ответ

4

Использование SendKeys и симулировать клавишу ВВОД. Получите помощь here.

Удачи.

+1

Спасибо за подсказку. Я использую консольное приложение, поэтому SendKeys может не работать - сейчас я изучаю его. – Contango

+0

Только что нашел http://inputsimulator.codeplex.com/, видимо, он может имитировать нажатия клавиш в консольных приложениях. – Contango

+0

Закончено с использованием http://inputsimulator.codeplex.com/. См. Полный ответ здесь: http://stackoverflow.com/questions/9016087/net-call-to-send-enter-keystroke-into-the-current-process-which-is-a-console – Contango

6

CLR налагает довольно правильные правила на состояние потока, когда он прерывает его. Опасности Thread.Abort() хорошо известны, что, безусловно, никогда не может работать надежно, прерывает поток, который выполняет неуправляемый код. В этом случае, когда вы вызываете Console.ReadLine(), поток зарывается глубоко внутри кода операционной системы Windows.

Вам нужно будет сделать это по-другому. Одним из очевидных подходов является то, что вы позволяете этому потоку «пользовательского интерфейса» останавливать программу, а не наоборот. Может быть так же просто, как команда «выйти» или сообщение «Нажать любую клавишу для продолжения».

Или установите для свойства IsBackground нити значение true. Теперь вам не нужно его прерывать, Windows завершит его, когда завершит процесс после того, как выйдет метод Main().

+0

Спасибо, что объяснил, что происходит здесь. У меня есть другая идея: как насчет того, чтобы выжать ключ [enter] в консольное приложение, заставляя поток проснуться и прервать? Есть способ сделать это: System.Windows.Forms.SendKeys.SendWait() – Contango

+0

Это слишком уродливо, SendKeys() очень ненадежно. Вы можете получить Console.ReadLine(), чтобы вернуться с помощью [закрытия дескриптора ввода консоли] (http://stackoverflow.com/a/9479797/17034) –

2

Я просто проверял, ни Thread.Abort(), ни Thread.Interrupt() работы на потоке, который вызывает к Console.ReadLine(), даже при вызове ее через StreamReader(new BufferedStream(...)).

Я даже пытался позвонить Console.In.Close() и Dispose().Кажется, когда вы читаете, вы действительно там; странно, потому что это, похоже, нарушает дизайн потоков.

Это действительно выглядит как ваш единственный вариант заключается в использовании ответ упоминаемый @ Дарин-Димитров

Edit: Немножко другой один из списка: Пробовал вызов Win32 API FreeConsole. Вызывает исключение повреждения памяти из вызова Console.ReadLine().

+0

У меня есть другая идея: как насчет того, чтобы вытащить ключ [enter] в консоль приложение, заставляющее поток просыпаться и прерываться? Существует способ: System.Windows.Forms.SendKeys.SendWait() – Contango

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