Как я могу иметь новый поток "взять на себя" стандартный ввод? - PullRequest
0 голосов
/ 19 октября 2011

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

Есть ли способ решить эту проблему?

Одна вещь, которую я попробовал, (в основном потоке):

while(foo) {
   if(busy) continue;
   fgets(input,200,stdin);
   if(busy) {
      fputs(input,stdin);
   } else {
      // do whatever was supposed to be done with input intended for main thread
   }
}

Но у меня, похоже, неправильное понимание того, как работают потоки, потому что другой вызов fgets не читает записанные данныечерез fputs.

Ответы [ 2 ]

1 голос
/ 19 октября 2011

Создание логической переменной, защищенной соответствующим примитивом синхронизации.Инициализируйте это как ложное.Когда поток должен задать пользователю вопрос и получить ответ, подождите, пока переменная не станет 'false' (в зависимости от выбранного вами примитива синхронизации), а затем установите для него значение true.Сделайте все выходные и получите все необходимые данные.Затем установите для переменной значение «false» и разблокируйте все ожидающие потоки (в зависимости от выбранного вами примитива синхронизации).

Для pthreads, мьютекс и переменная условия, вероятно, являются лучшими.Для Windows критический раздел и событие автоматического сброса, вероятно, лучше всего.

В вашем вопросе отсутствуют некоторые детали, которые могут предложить другой ответ.Как пользователь должен взаимодействовать с программой, когда он не может быть уверен, какой из двух отдельных путей кода получит ввод, который он вводит?Если он что-то наберет, а затем нажмет «Enter», то путь к коду, который он использует, может зависеть от того, нажмет ли он «Enter» до того, как другой поток будет готов, или нет, что может создать непригодную программу.Почти в каждом реалистическом случае вам нужно будет запросить пользователя, затем дождаться ответа, а затем одновременно разблокировать ввод и вывод.

0 голосов
/ 19 октября 2011

Для потомков вот как я решил это.

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

Приведенный выше фрагмент становится:

while(foo) {
   fgets(input,200,stdin);
   if(busy) {
      busyStuff(input);
   } else {
      nonBusyStuff(input);
   }
}

, и никакой другой pthread с вызовом fgets никогда не создается.

...