0

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();
        }
    }
}

さて、問題は、コンソールに「5秒経過しました!」と表示されたときです。(スレッドを中止した後t2)、すぐには終了しません。このテキストは数秒間表示された後、コンソールが終了します。

問題は、スレッドが中止される前に(メソッドの) キーを押すとReadKey、「5 秒が経過しました!」と表示されることです。text で、すぐに終了します。

どのキーもクリックReadKeyせず、メソッドが実行されない場合、テキストが数秒間表示されるだけです。

何故ですか?バグですか?そして、私はそれを修正できますか?

4

2 に答える 2

0

あなたが見ている結果は私には合理的だと思われます。呼び出しThread.Abortてもコンソールのブロックが解除されるわけではないので、入力を待っています。Thread.Abortいずれにせよ、期待どおりに動作するという保証はないため、電話は避けるべきです。キャンセルのサポートをスレッドに組み込む方がはるかに優れたアプローチであり、これを行うにはさまざまな方法があります。

または、すべてが既に組み込まれているTask Parallel Libraryを使用するだけです。

于 2013-10-11T12:46:44.730 に答える
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.
  }
}
于 2013-10-11T14:31:22.667 に答える