2013-10-11 147 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. 
    } 
}