0

過去 2 日間に発生したこの問題を解決するための正しい方向へのポインタを誰かに教えていただければ、非常に感謝しています。私は Visual Studio 2010 コンソール用のタイピング ソフトウェアに取り組んでおり、時間を表現する必要があります。同時にキーボードからの入力を得ることができます。

問題は、ReadLine() メソッドを使用すると、タイマー スレッドがスリープしているときにのみ書き込みが可能になることです。デリゲートまたは高度なタスク継続メソッドを使用して解決できる可能性があります。これらは新しい概念であるため、少し混乱しています。コードは次のとおりです (見苦しい書式で申し訳ありません)。

using System;
using System.Threading.Tasks;
using System.Threading;


namespace Typing_Game_tests
{

    class Input_and_timer_multithread
    {
        public static void TimerThread() 
        { 
            for (int i = 1, mins = -1; i <= 1860; i++) 
            {
                Console.SetCursorPosition(0, 0);
                if (i % 60 == 1) 
                { 
                    mins++; 
                }

                Console.WriteLine("Timer: " + mins +  " minute(s) and " + i % 60 + " seconds elapsed");            

                Console.SetCursorPosition(0, 6); 
                Thread.Sleep(1000);
            }
        }


        static string keysRead;

        public static void GetInput()
        {
            while (Console.ReadKey(true).Key != ConsoleKey.Enter)
            {
                Console.SetCursorPosition(0, 6);
                keysRead = Console.ReadLine();
                Console.SetCursorPosition(0, 6);
            }

            Console.SetCursorPosition(0, 6);
            Console.WriteLine(keysRead);

        }

        static void Main(string[] args)
        {               
            Thread timerMain = new Thread(new ThreadStart(TimerThread));
            timerMain.Start();
            Task getinputMain = new Task(GetInput);
            getinputMain.Start();
        }
     }
  }

私が見つけて研究したほとんどの例には、ラムダ式とデリゲートが含まれています。これらは、私がまだ理解して実装するのに苦労している新しい主題です。ReadLine() が機能するまでメイン タイマー スレッドを停止できればもっと簡単だったでしょうが、意味がありません。さらに、Timers 名前空間を使用してみましたが、同じ問題がありました。

カーソルがユーザーからの入力を永続的に取得しているという印象を与えたかったのですが、デッドロックせずにスレッドを効率的に切り替える方法をまだ見つけていません。ありがとう。

4

1 に答える 1

2

この種のコードは、.NET 4.5 以降では機能しません。Console.ReadKey() および ReadLine() は、他のスレッドがコンソールに書き込めないようにするロックを取得します。ロックが取れないように交換する必要があります。これには、Console.KeyAvailable でキーボードをポーリングする必要があります。以下は、Console.ReadLine() の単純な置換メソッドです。

static object ConsoleLock = new object();

static string ReadString() {
    var buf = new StringBuilder();
    for (; ; ) {
        while (!Console.KeyAvailable) System.Threading.Thread.Sleep(31);
        lock(ConsoleLock) {
            var key = Console.ReadKey(true);
            if (key.Key == ConsoleKey.Enter) {
                Console.WriteLine();
                return buf.ToString();
            }
            else if (key.Key == ConsoleKey.Backspace) {
                if (buf.Length > 0) {
                    buf.Remove(buf.Length - 1, 1);
                    Console.Write("\b \b");
                }
            }
            else {
                buf.Append(key.KeyChar);
                Console.Write(key.KeyChar);
            }
        }
    }
}

また、カーソルを移動する他のスレッドで ConsoleLock をロックして、出力が厳密に分離されるようにします。

于 2013-06-18T01:53:55.800 に答える