在C#中运行计时器时无法写入任何内容 [英] Can't write anything while the timer is running in C#

查看:94
本文介绍了在C#中运行计时器时无法写入任何内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经制作了一个从10开始倒退的计时器。我想创建一个简单的小游戏。我想在10秒钟内写下我喜欢编程的句子如果能够这样做的话,应该显示的信息'你是win,gratz'但是当时钟耗尽时,消息应该显示为你输了,但它没有拿起句子,当我写的时候,它消失了。我试着这里做的是我的代码。



我尝试了什么:



I have made a timer which runs backwards starting from 10.I just wanna create a little simple game.I wanna write the sentence 'I love programming' under 10 seconds if i am able to do it the message should shown 'You win , gratz' but when the clock runs out of time the message should be shown 'you lose' but its not picking up the sentence and when I write,it disappears.I tried doing it here is my code.

What I have tried:

class Program
   {
       static Timer timer = new Timer(1000);
       static int i = 10;

       static void Main(string[] args)
       {
           Console.WriteLine("Write the sentence in 10 seconds");
           Console.WriteLine("I love programming");
           Console.ReadKey();
           timer.Elapsed += timer_Elapsed;
           timer.Start();
           Console.Read();
       }

       private static void timer_Elapsed(object sender, ElapsedEventArgs e)
       {
           i--;
           Console.Clear();
           Console.WriteLine("=======================");
           Console.WriteLine("  Time is running out       ");
           Console.WriteLine("");
           Console.WriteLine("The Clock starts: {0}", i.ToString());
           Console.WriteLine("");
           Console.WriteLine("=======================");

           while (true)
           {
               if (Console.ReadLine() == "I love programming")
               {
                   Console.Clear();
                   Console.WriteLine("=======================");
                   Console.WriteLine("     You Win                     ");
                   Console.WriteLine("");
                   Console.WriteLine("     Gratz                      ");
                   Console.WriteLine("");
                   Console.WriteLine("=======================");
                   timer.Stop();
                   timer.Dispose();

               }
           }

           GC.Collect();
       }
   }

推荐答案

问题是计时器Elapsed事件是在启动它的线程 - 调用Console.Read的同一个线程。

不幸的是,Console.Read是一个阻塞调用 - 它在用户输入完成之前不会返回,这意味着用户按下ENTER。



您需要做的是将Timer移动到另一个线程,以便它可以独立于您的主代码运行。但是......这对你不起作用,因为你的Elapsed代码也试图从用户那里读取输入,而ReadLine也是一个阻塞调用。所以在用户输入ENTER之前它不会继续!并且你在Elapsed方法中永远循环,所以永远不会结束!但更糟糕的是,你有两个竞争线程试图从相同的输入读取,那么哪个人会得到什么是任何人的猜测!



你要做的事情非常复杂:你需要完全停止使用阻塞调用:这意味着你必须开始思考非常非常不同。 />
这可以作为控制台应用程序完成:如何阅读用户写的内容(无需点击输入) - 控制台C# - Stack Overflow [ ^ ]但它是非常先进的东西。我强烈建议您在使用Windows应用程序而不是控制台应用程序时保留一到两周,这些应用程序更适合多线程工作,定时器和非阻塞输入!
The problem is that the timer Elapsed event is raised on the thread that started it - the same thread that calls Console.Read.
Unfortunately, Console.Read is a blocking call - it doesn't return until the user input is complete, and that means the user pressing ENTER.

What you need to do is move the Timer onto a different thread so that it can operate independently of your main code. But ... that won't work for you either because your Elapsed code is also trying to read input from the user and ReadLine is also a blocking call. So it won't continue until the user types ENTER either! And you are looping forever inside the Elapsed method, so that will never end! But to make matters worse, you then have two competing threads trying to read from the same input, so what which one is going to get what is anybody's guess!

What you are trying to do is surprisingly complex: you will need to stop using blocking calls completely: which means you have to start thinking very, very differently.
This can be done as a console app: How to read what user wrote (without hitting enter) - console C# - Stack Overflow[^] but it's pretty advanced stuff. I'd strongly suggest that you leave this for a week or two when you get to Windows applications instead of Console ones which are much, much more suitable for multithreaded work, timers, and non-blocking inputs!

您必须从控制台异步读取字符,将它们添加到字符串中并在计时器处理程序上报告此类字符串。快速而肮脏的解决方案可能类似于

You have to asynchronously read characters form the console, add them up to a string and report such a string on timer handler. A quick and dirty solutions could be something like
class Program
{
    static Timer timer = new Timer(1000);
    static int i = 10;
    static string sin;

    static void Main(string[] args)
    {
        sin = string.Empty;
        Console.WriteLine("Write the sentence in 10 seconds");
        Console.WriteLine("I love programming");
        timer.Elapsed += timer_Elapsed;
        timer.Start();
        while (i != 0)
        {
            if (Console.KeyAvailable)
            {
                sin += Console.ReadKey(true).KeyChar;
            }
        }
        timer.Stop();
        if (sin == "I love programming")
            Console.WriteLine("OK");
        else
            Console.WriteLine("KO");
    }

    private static void timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        i--;
        Console.Clear();
        Console.WriteLine("=======================");
        Console.WriteLine("  Time is running out       ");
        Console.WriteLine("");
        Console.WriteLine("The Clock starts: {0}", i.ToString());
        Console.WriteLine("");
        Console.WriteLine(sin);
        Console.WriteLine("=======================");
    }
}


这篇关于在C#中运行计时器时无法写入任何内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆