Подтвердить что ты не робот

Как прервать другой поток в .NET, когда указанный поток выполняет Console.ReadLine?

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

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

this.UserInterfaceThread.Abort();

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

Обновление

Как указал Ханс Пассант:

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

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

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

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

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

.NET-вызов для отправки [enter] нажатия клавиши в текущий процесс, который представляет собой консольное приложение?

4b9b3361

Ответ 1

Используйте SendKeys и имитируйте клавишу ENTER. Получите справку здесь.

Удачи.

Ответ 2

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

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

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

Ответ 3

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

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

По-видимому, ваш единственный вариант - использовать ответ, упомянутый @Darin-Dimitrov

Изменить: Сбил еще один из списка: Пробовал вызывать win32 api FreeConsole. Вызывает исключение повреждения памяти из вызова Console.ReadLine().