我试图多次使用一个线程,如果用户反应不够快,让线程停止处理。
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 :(得分:2)
方法Thread.Join(Int32)
在给定的毫秒数后不会停止另一个线程。它只是停止等待。如果另一个线程已终止,则返回true。
因此,如果ask.Join(30000);
返回false,则另一个线程仍在运行,您必须自行中止该线程。
答案 1 :(得分:0)
你有什么证据表明提示线程没有终止?主线程应该等待提示线程在“连接”位置终止,因此,如果执行继续通过连接,则“提示”线程终止。
答案 2 :(得分: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.
}
}
答案 3 :(得分:0)
查看MSDN Thread.Join()页面上的示例。该示例使用两种不同的方法将工作传递给线程。 regularThread
正是您要做的。对于您示例中的简单任务,我认为在没有事件或锁的情况下执行join()是一种合理的解决方案。如果您正在进行原型设计以制作比您的示例所暗示的更强大的产品,那么您还应该:1)阅读ThreadPool。它避免了创建/处置线程的成本。 2)对answer
变量的读写进行lock()块。
警告:其他答案提到使用Thread.Abort()。在当前正在执行的线程上调用Thread.Abort()很好,几乎等同于抛出异常。但是应该避免在不同的线程上调用Thread.Abort()。有几种情况会导致线程无法正常清理。