C# 控制台应用程序中的消息泵

C# 控制台应用程序中的消息泵,c#,.net,console-application,message-pump,C#,.net,Console Application,Message Pump,我有一个用.NET编写的相当简单的控制台应用程序。有时,应用程序在没有操作员的情况下以批处理模式运行,有时则“自费”运行。如果在批处理模式下运行,则有一个已定义的默认选项,允许程序自动运行。如果有操作员在场,则有其他选项允许用户从功能列表中进行选择 出于我不想深入讨论的原因,命令行参数不是首选参数。相反,我创建了一个10秒的窗口,操作员可以在其中选择一个函数。目前,我正在使用一个简单的while循环并从“in”流读取输入。我在末尾添加了一个调用,以防止while循环完全消耗处理器,但我想知道是否

我有一个用.NET编写的相当简单的控制台应用程序。有时,应用程序在没有操作员的情况下以批处理模式运行,有时则“自费”运行。如果在批处理模式下运行,则有一个已定义的默认选项,允许程序自动运行。如果有操作员在场,则有其他选项允许用户从功能列表中进行选择

出于我不想深入讨论的原因,命令行参数不是首选参数。相反,我创建了一个10秒的窗口,操作员可以在其中选择一个函数。目前,我正在使用一个简单的while循环并从“in”流读取输入。我在末尾添加了一个调用,以防止while循环完全消耗处理器,但我想知道是否有更好的方法

在Windows应用程序(或)中,有一个消息泵,它能够读取消息队列,然后将控制权返回给系统。即使是像VisualStudio这样的重载应用程序,在空闲时也会占用几乎0%的处理器。我的控制台应用程序能达到同样的效果吗

线程。睡眠是有效的,但是,正如我所说,我想知道是否有更好的方法

以下是源代码:

class Program {
    static void Main( string[] args ) {

        DateTime l_startTime = DateTime.Now;

        Console.CursorVisible = false;
        Console.WriteLine( "Please select an option within 10 seconds..." );
        Console.WriteLine( "" );
        Console.WriteLine( " [1] Option A (DEFAULT)" );
        Console.WriteLine( " [2] Option 2" );
        Console.WriteLine( " [3] Option III" );

        int l_elapsedSeconds = 0;

        bool l_exit = false;
        while ( !l_exit ) {

            int l_currentElapsedSeconds = (int) Math.Floor( ( DateTime.Now - l_startTime ).TotalSeconds );
            if ( l_currentElapsedSeconds > l_elapsedSeconds ) {
                Console.CursorTop = 0;
                Console.CursorLeft = 0;
                l_elapsedSeconds = l_currentElapsedSeconds;

                int l_remainingSeconds = 10 - l_elapsedSeconds;

                Console.WriteLine( String.Format( "{0,-80}", "Please select an option within " + l_remainingSeconds + " seconds..." ) );
            }

            if ( l_elapsedSeconds >= 10 ) {
                OptionA();
                break;
            }

            if ( Console.KeyAvailable ) {
                var l_key = Console.ReadKey( true );

                switch ( l_key.Key ) {
                    case ConsoleKey.D1:
                        OptionA();
                        l_exit = true;
                        break;

                    case ConsoleKey.D2:
                        Option2();
                        l_exit = true;
                        break;

                    case ConsoleKey.D3:
                        OptionIII();
                        l_exit = true;
                        break;
                }
            }

            if ( !l_exit )
                // Don't eat all the processor
                System.Threading.Thread.Sleep( 100);
        }

        Console.CursorTop = 7;
        Console.CursorLeft = 0;

        Console.Write( "Press any key to continue...");
        Console.ReadKey( true);

    }

    static void OptionA() {
        Console.CursorTop = 6;
        Console.CursorLeft = 0;

        Console.WriteLine( "Option A Selected!");
    }

    static void Option2() {
        Console.CursorTop = 6;
        Console.CursorLeft = 0;

        Console.WriteLine( "Option 2 Selected!");
    }

    static void OptionIII() {
        Console.CursorTop = 6;
        Console.CursorLeft = 0;

        Console.WriteLine( "Option III Selected!");
    }
}

注意:此问题与超时无关。。。它是关于在等待响应时使用0%的处理器时间(如窗口应用程序)。

您可以启动一个线程,在后台读取按键。将密钥添加到阻塞队列,并在主线程中等待队列被填充,例如

var queue = new BlockingCollection<ConsoleKeyInfo>();

new Thread(() =>
{
    while (true) queue.Add(Console.ReadKey(true));
})
{ IsBackground = true }.Start();


Console.Write("Welcome! Please press a key: ");

ConsoleKeyInfo cki;

if (queue.TryTake(out cki, TimeSpan.FromSeconds(10))) //wait for up to 10 seconds
{
    Console.WriteLine();
    Console.WriteLine("You pressed '{0}'", cki.Key);
}
else
{
    Console.WriteLine();
    Console.WriteLine("You did not press a key");
}
var queue=newblockingcollection();
新线程(()=>
{
while(true)queue.Add(Console.ReadKey(true));
})
{IsBackground=true}.Start();
控制台。写:“欢迎!请按一个键:”;
ConsoleKeyInfo-cki;
if(queue.TryTake(out cki,TimeSpan.FromSeconds(10))//最多等待10秒
{
Console.WriteLine();
WriteLine(“您按下了{0}',cki.Key);
}
其他的
{
Console.WriteLine();
WriteLine(“您没有按键”);
}

后台线程和主线程在分别等待ReadKey和TryTake返回时都将休眠(利用0%的处理器时间)。

您可以使用.NET的事件处理机制。转载自

导入System.Threading.Thread
模块1
私有秒作为整数=1
私人勾号作为新计时器。计时器(1000)
副标题()
AddHandler tick.appeased,计时器tick的AddressOf Ticker事件
Dim NEWTREAD As System.Threading.Thread=New System.Threading.Thread(LookForKeyPress的地址)'检查按键的新线程
NewThread.Start()'启动线程
Console.WriteLine(“正在等待按键…”)
勾选.Enabled=True'启用计时器
端接头
私人分票机()
'每个勾号都会调用此sub,并显示秒数,直到按下一个键
控制台写入线(秒)
秒+=1
端接头
私有子LookForKeyPress()
虽然是真的
Dim k As ConsoleKeyInfo=Console.ReadKey()'为按键读取

如果不是k.Key.ToString.Length对我来说似乎是个不错的方法。我玩了一会儿,没有看到任何比这更好的东西。+1啊!我喜欢这个答案,但我的公司仍然停留在中世纪(.net 3.5)至少6个月。我得等到回家后再试试。再看一眼,虽然我喜欢这种方法,但我还是想在后台做一些处理(一个小倒计时器,让用户知道还有多少时间按下一个键)。让线程睡眠整整10秒钟并不是我想要做的事情,但我想可以对这种方法进行一些调整,以获得所需的行为。如果这个问题没有结束,我希望得到更多的答案,但现在看来这是我唯一能得到的答案。
Imports System.Threading.Thread

Module Module1
    Private Second As Integer = 1
    Private Tick As New Timers.Timer(1000)

    Sub Main()

        AddHandler tick.Elapsed, AddressOf Ticker 'Event for the timer tick

        Dim NewThread As System.Threading.Thread = New System.Threading.Thread(AddressOf LookForKeyPress) 'New thread to check for key press
        NewThread.Start() 'Start thread

        Console.WriteLine("Now awaiting key presses...")
        tick.Enabled = True 'Enable the timer
    End Sub

    Private Sub Ticker()
        'every tick this sub is called and the seconds are displayed till a key is pressed
        Console.WriteLine(Second)
        Second += 1

    End Sub

    Private Sub LookForKeyPress()

        While True
            Dim k As ConsoleKeyInfo = Console.ReadKey() 'read for a key press
            If Not k.Key.ToString.Length <= 0 Then 'check the length of the key string pressed, mainly because the key in this case will be apart of the system.consolekey
                Console.WriteLine(Environment.NewLine & "Key Pressed: " & k.Key.ToString) 'display the key pressed
                Second = 1 'restart the timer
            End If
        End While

    End Sub

End Module