2011-01-21 4 views
0

Я пытаюсь использовать поток несколько раз и обрабатывать стоп-поток, если пользователь не реагирует достаточно быстро.Использование потока Несколько раз

Thread ask = new Thread (new ThreadStart (MathQuiz.prompt)); 
ask.Start(); 
ask.Join(30000); 
if (answer == 4) 
{ 
    score = score+1; 
    answer = 0; 
} 
Console.WriteLine(); 
Console.WriteLine("Press any key to move on to the next question!"); 
Console.WriteLine(); 
Console.ReadKey(true); 
Console.WriteLine("What is 15/3?"); 
Console.WriteLine(); 
ask.Start(); 
ask.Join(30000); 
if (answer == 5) 
{ 
    score = score+1; 
    answer = 0; 
} 

...

static void prompt() 
    { 
    preanswer = (Console.ReadLine()); 
    if (!decimal.TryParse(preanswer, out answer)) 
     { 
      Console.WriteLine("That wasn't even a number or decimal!"); 
     } 
    else 
     { 
      answer = decimal.Parse(preanswer); 
     } 
    } 

Прямо сейчас это не кажется, что «приглашение» нить завершения, и поэтому он выходит из строя, когда начинается второй вопрос.

Так что мне нужно решение! Я, конечно, не против отвечать на вопросы, чтобы помочь себе получить ответ.

+0

Возможно, вы захотите посмотреть на этот вопрос, для решения, которое, по моему мнению, релевантно: http://stackoverflow.com/questions/142826/is-there-a-way-to-indefinitely-pause-a-thread/143153 # 143153 – blueberryfields

ответ

0

Какие у вас есть доказательства того, что строка запроса не заканчивается? Основной поток должен ждать, пока строка запроса будет завершена в местах объединения, поэтому, если выполнение продолжается после соединения, поток «prompt» завершается.

+0

Не дожидаясь его завершения, он ждет 30 секунд. –

+0

Справа. Он не использует возвращаемое значение для чего-либо. – blueberryfields

+0

Как получить это возвращаемое значение и проверить его? –

2

Метод Thread.Join(Int32) не останавливает другой поток после заданного количества миллисекунд. Он просто перестает ждать. Он возвращает true, если другой поток завершен.

Так что если ask.Join(30000); возвращает false, другой поток все еще работает, и вы должны сами прервать поток.

+0

Как я могу прервать поток? –

0

Console.ReadLine блокирует текущий поток от прерывания до тех пор, пока линия не будет считана. (В соответствии с комментарием от Timwi)

Чтобы обойти эту проблему, вы должны использовать метод Console.KeyAvailable здесь: How to add a Timeout to Console.ReadLine()?

Я переписал эту проблему, прежде чем понял свою ошибку, и теперь вот решение.

Это скорее более активное участие, чем я хотел. (Использование KeyAvailable означает, что я должен стоять в очереди клавиши ввода и поддержки забой я должен удалить элементы. Мне также нужно спать в то время как ни одна из клавиш не доступны ...)

private static AutoResetEvent answered = new AutoResetEvent(false); 
private static Func<string, bool> questionCorrect = null; 
private static bool? correct; 

static void Main(string[] args) 
{ 
    int score = 0; 
    AskQuestion(ref score, 
       "What is 15/3?", 
       TimeSpan.FromSeconds(5), 
       answer => 
        { 
         decimal value; 
         if (!decimal.TryParse(answer, out value)) 
         { 
          Console.WriteLine(
           "That was not a valid number"); 
          return false; 
         } 

         return (value == 15/3); 

        }); 


    AskQuestion(ref score, 
       "What is 20 * 2 ?", 
       TimeSpan.FromSeconds(5), 
       answer => 
        { 
         decimal value; 
         if (
          !decimal.TryParse(answer, 
               out value)) 
         { 
          Console.WriteLine(
           "That was not a valid number"); 
          return false; 
         } 

         return (value == 20*2); 

        }); 


    Console.WriteLine("Done. Score: {0}", score); 
    Console.ReadLine(); 
} 

private static void AskQuestion(ref int score, string question, TimeSpan duration, Func<string, bool> validator) 
{ 
    // Setup 
    questionCorrect = validator; 
    correct = null; 
    answered.Reset(); 

    // Ask 
    Console.WriteLine(question); 
    Thread thread = new Thread(GetQuestion); 
    thread.Start(); 

    // Wait 
    answered.WaitOne(duration); 
    thread.Abort(); 
    thread.Join(); 

    Console.WriteLine(); // Write empty line, otherwise this overwrites the answer. 

    // Validate); 
    if (correct.HasValue && correct.Value == true) 
    { 
     score++; 
     Console.WriteLine("Correct"); 
    } 
    else if (correct.HasValue) 
    { 
     Console.WriteLine("Incorrect"); 
    } 
    else 
    { 
     Console.WriteLine("Timeout"); 
    } 

} 

private static void GetQuestion() 
{ 
    try 
    { 
     List<char> captured = new List<char>(); 
     bool answerCaptured = false; 
     while (!answerCaptured) 
     { 
      while (Console.KeyAvailable) 
      { 

       var key = Console.ReadKey(); 
       if (key.KeyChar == '\r' || key.KeyChar == '\n') 
       { 
        answerCaptured = true; 
        break; 
       } 

       if (key.KeyChar == '\b' && captured.Count > 0) 
       { 
        captured.RemoveAt(captured.Count - 1); 
       } 
       else 
       { 
        captured.Add(key.KeyChar); 
       } 
      } 
      Thread.Sleep(50); 
     } 
     string answer = new string(captured.ToArray()); 

     correct = questionCorrect.Invoke(answer); 
     answered.Set(); 
    } 
    catch (ThreadAbortException) 
    { 
     // will be thrown when the thread times out. 
    } 
} 
+0

Я попробовал это и нашел требование в вашем первом предложении ошибочным. 'Console.ReadLine' не блокирует другие потоки. – Timwi

+0

@ Тимви - Кажется, в этом случае. Отредактировал мой ответ, чтобы разрешить переключение между методами ввода. Пожалуйста, не стесняйтесь указать, что я сделал неправильно. –

+0

@Will: Я пробовал еще немного, и кажется, что 'thread.Abort()' просто не прерывает поток, пока он находится внутри 'Console.ReadLine()'. – Timwi

0

Взгляните пример на странице MSDN Thread.Join(). В этом примере используются два разных метода передачи работы в поток. regularThread - это то, что вы пытаетесь сделать. Для простой задачи в вашем примере, я думаю, что создание соединения() без событий или блокировок является разумным решением. Если вы прототипируете, чтобы сделать продукт более надежным, чем ваш пример, то вы также должны: 1) прочитать на ThreadPool. Это позволяет избежать затрат на создание/удаление потоков. 2) Поместите блок lock() вокруг чтения и записи в переменную answer.

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

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