2013-10-11 117 views
0

以下是我在C#中做了一个代码:C# - 多线程暂停

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 

namespace xyz 
{ 
    class Program 
    { 
     Thread t1, t2; 
     static void Main(string[] args) 
     { 
      Program go = new Program(); 
      go.actual(); 
     } 
     public void actual() 
     { 
      t1 = new Thread(timer); 
      t2 = new Thread(inputting); 
      t1.Start(); 
      t2.Start(); 
     } 
     public void timer() 
     { 
      Thread.Sleep(5000); 
      t2.Abort(); 
      Console.WriteLine("5 seconds passed!"); 
     } 
     public void inputting() 
     { 
      Console.WriteLine("Please wait 5 seconds..."); 
      Console.ReadKey(); 
     } 
    } 
} 

现在的问题是,当控制台说:“五秒钟过去了!” (在中止t2线程之后),它不会立即退出。这段文字停留在那里几秒钟,然后控制台退出。

问题是,如果我在线程中止之前按下键(方法ReadKey),它会显示“5秒通过!”文本,然后马上退出。

如果我不点击任何键,并且ReadKey方法不会发生,它只会显示文本几秒钟。

这是为什么?这是一个错误吗?我能解决它吗?

+0

因为它清理线程?我想不出任何其他原因。 –

+0

是的,但是如果我终止了具有“Console.ReadKey()”的线程,则ReadKey命令也应该中止,因为它是我中止的线程的一部分。 – BlueRay101

+0

1.不要放弃线程,只是要求麻烦,2.为什么要创建一个'Program'的新实例?只需调用'actual'即可。 – James

回答

0

您看到的结果对我来说似乎合理,呼吁Thread.Abort不会以某种方式解锁控制台,因此它仍将等待输入。无论如何,你应该避免调用Thread.Abort,因为不能保证它能按预期工作。这是一个更好的方法来建立对你的线程的取消支持,并有多种方式来做到这一点。

另外,只需使用Task Parallel Library它已全部建立。

0

从您的意见,我看到你基本上想在一段时间后超时Console.ReadKey电话。不幸的是,ReadKey没有超时参数。好的,可以。我们可以用一种方法来包装它。您不需要使用任何异步机制来完成此操作。只需在同步轮询循环中使用Console.KeyAvailable即可。

public static class ConsoleEx 
{ 
    public static bool TryReadKey(TimeSpan timeout, out ConsoleKeyInfo keyinfo) 
    { 
    var cts = new CancellationTokenSource(); 
    return TryReadKey(timeout, cts.Token, out keyinfo); 
    } 

    public static bool TryReadKey(TimeSpan timeout, CancellationToken cancellation, out ConsoleKeyInfo keyinfo) 
    { 
    keyinfo = new ConsoleKeyInfo(); 
    DateTime latest = DateTime.UtcNow.Add(timeout); 
    do 
    { 
     cancellation.ThrowIfCancellationRequested(); 
     if (Console.KeyAvailable) 
     { 
      keyinfo = Console.ReadKey(); 
      return true; 
     } 
     Thread.Sleep(1); 
    } 
    while (DateTime.UtcNow < latest); 
    return false; 
    } 
} 

然后你会这样使用它。

public static void Main() 
{ 
    ConsoleKeyInfo cki; 
    if (ConsoleEx.TryReadKey(TimeSpan.FromSeconds(5), out cki)) 
    { 
    Console.WriteLine("ReadKey returned a value."); 
    } 
    else 
    { 
    Console.WriteLine("ReadKey timed out. 
    } 
}