0

如果有人能给我一个正确的方向来解决我在过去两天遇到的这个问题,我将非常感激:我正在为 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();
        }
     }
  }

我发现和研究的大多数示例都有 lambda 表达式和委托,这是我在理解和实施方面仍然存在一些困难的新主题。如果我可以在 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 回答