C# 实时显示字符串值

C# 实时显示字符串值,c#,multithreading,real-time,C#,Multithreading,Real Time,我正在编写一个控制台程序,代码如下所示: 配置.cs public static class Configuration { public static string Message = ""; } Menu.cs class Menu { public static void showMenu() { Console.Clear(); Console.WriteLine("1: SOMETHING"); Console.

我正在编写一个控制台程序,代码如下所示:

配置.cs

public static class Configuration
{
    public static string Message = "";
}
Menu.cs

class Menu
{
    public static void showMenu()
    {
        Console.Clear();
        Console.WriteLine("1: SOMETHING");
        Console.WriteLine("2: SOMETHING");
        Console.WriteLine("3: SOMETHING");
        Console.WriteLine("SYSTEM MSG: " + Configuration.Message);
        Console.Write("INPUT: ");
    }
}
Program.cs

...
static void Main(string[] args)
{
    ...
    int choice;

    while(true)
    {
        Menu.showMenu();
        choice = Convert.ToInt32(Console.ReadLine());

        switch(choice)
        {
            case 1:
            Configuration.Message = "HELLO!";
            break;

            case 2:
            Configuration.Message = "HI!";
            break;

            case 3:
            Configuration.Message = "WHAT?!";
            break;
        }
    }
}
...
现在,当我更改Configuration.Message时,它将显示在菜单上,因为showMenu方法会清除控制台并再次显示字符串


但我想做的是,没有明确的方法,我想实时显示Configuration.Message。我在想,使用定时器和刷新菜单每秒钟,但这是没有效率的(感觉像作弊)。我怎样才能做到这一点呢?

我建议,如果像这样的功能是必要的,最好看看像WPF这样的UI技术。但是,尽管如此,也许这会满足你的要求。每次设置消息时显示菜单。我认为在使用控制台时,没有办法将变量绑定到控制台上的某个消息

    public static class Configuration
    {
        private static string _message;
        public static string Message 
        { 
            get
            {
                return _message;
            }
            set
            {
                _message = value;
                Menu.showMenu();
            }
        }
    }
编辑:要使用属性更改事件实现此功能,可以执行以下操作。注意,我没有实现
INotifyPropertyChanged
来保持静态类

class Program
    {
        static void Main(string[] args)
        {
            Configuration.PropertyChanged += (sender, e) =>
            {
                Menu.showMenu();
            };
            int choice;

            while (true)
            {
                Menu.showMenu();
                choice = Convert.ToInt32(Console.ReadLine());

                switch (choice)
                {
                    case 1:
                        Configuration.Message = "HELLO!";
                        break;

                    case 2:
                        Configuration.Message = "HI!";
                        break;

                    case 3:
                        Configuration.Message = "WHAT?!";
                        break;
                }
            }
        }
    }

    class Menu
    {
        public static void showMenu()
        {
            Console.Clear();
            Console.WriteLine("1: SOMETHING");
            Console.WriteLine("2: SOMETHING");
            Console.WriteLine("3: SOMETHING");
            Console.WriteLine("SYSTEM MSG: " + Configuration.Message);
            Console.Write("INPUT: ");
        }
    }

    public static class Configuration 
    {
        public static event PropertyChangedEventHandler PropertyChanged;

        private static string _message;
        public static string Message
        {
            get
            {
                return _message;
            }
            set
            {
                if (value != _message)
                {
                    _message = value;
                    NotifyPropertyChanged(property: _message);
                }
            }
        }

        private static void NotifyPropertyChanged(object property, String propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(property, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

当用户点击enter键时显示菜单。

除非响应用户的输入,否则写入控制台不是一个好主意。这样做的原因是你可以在控制台中间向他们输入他们想要的线。然后他们的文本和退格键将变得不同步,用户将很难理解发生了什么

我的建议是添加另一个选项,这样用户只需点击
ENTER
,无需选择,即可重新显示菜单而无需清除。这将允许用户通过点击
ENTER
而不选择选项来决定何时实时刷新


如果您确实希望采用更实时的方法,并且希望将其与用户输入相结合,我建议控制台不是提供此解决方案的好方法。

当您写入
控制台时,写入操作从当前光标位置开始。所以

查看类的属性和方法,尤其是:

  • CursorLeft
    获取或设置光标的列位置
  • CursorTop
    获取或设置光标的行位置
  • SetCursorPosition(int left,int top)
    设置行和列的位置
写入每个字符时,光标向右移动一个位置,当光标将移动超过
BufferWidth
列时,光标将换行到下一行(例如,如果控制台的缓冲区为80列宽,则写入第80列将使列前进到缓冲区外(第81列),因此光标将移动到下一行的第1列

对于您想要做的事情,您还可以查看调用本机Win32游标方法的p/函数,或者使用类似于*nix和Gnu的.Net派生:

  • 莫诺诅咒:
  • 诅咒犀利:
  • 诅咒X:

+1.
菜单
绝对应该是依赖项,而不是静态调用…甚至实现和连接
INotifyPropertyChanged
。但可以作为起点。@AlexeiLevenkov我同意
INotifyPropertyChanged
将是一种更干净的方法,特别是如果
配置中有更多成员的话对该消息进行分类。在使用控制台时,尤其是在使用
readLine
时,您应该非常小心地控制写入操作,以免在读取时发生写入操作。将对
showMenu
的调用放入
Configuration
类中,写入控制台会破坏此模型并混淆flow向控制台写入文本。不建议这样做。@ErickRobertson这是一个很好的观点。我和你一样建议,如果这样的功能是必要的,最好看看像WPF这样的UI技术。@AlexeiLevenkov我使用
PropertyChangedEvent
控制台消息和isplaying实时字符串是不兼容的想法。Winforms或WPF应用程序可以通过用户输入实时显示,因为您有多个线程。控制台并不是为此而构建的。@paqogomez不是多个线程让它在其他类型的GUI中工作,而是您有完全不同的媒体来显示输出t和收集输入。控制台将两者混合在一起的事实是导致问题的原因。请注意,控制台/终端输入/输出长期为人们工作……我认为这里的问题是OP依赖于控制台的绝对默认行为,这确实很难混合输入和输出-接管输入/输出(即使只是使用
Console.SetCursorPosition
打印到特定位置)将使之成为可能。+1这当然是功能齐全的方式。我强烈建议您确保所有控制台交互都在同一线程中完成。无论您选择哪种解决方案,这将确保您能够创造尽可能最好的用户体验。