【问题标题】:Console application does not accept input when a windows form is displayed显示 Windows 窗体时控制台应用程序不接受输入
【发布时间】:2013-01-07 07:00:15
【问题描述】:

我创建了一个控制台应用程序。我想让标签(在表单上)显示我在控制台中输入的任何内容,但是当我运行表单时控制台会挂起。

代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ConsoleApplication1
{
    class Program
    {
        Label a;
        static void Main(string[] args)
        {
            Form abc = new Form(); 
            Label a = new Label();
            a.Text = "nothing";
            abc.Controls.Add(a);
            Application.Run(abc);
            System.Threading.Thread t=new System.Threading.Thread(Program.lol);
            t.Start();


        }
        public static void lol()
        {
            Program p = new Program();
            string s = Console.ReadLine();
            p.a.Text = s;
            lol();
        }


    }
}

【问题讨论】:

    标签: c# winforms multithreading console


    【解决方案1】:

    Application.Run 将阻塞直到表单关闭。所以你应该在一个单独的线程上调用 that

    但是,您的 UI 将在该单独线程上执行 - 您不能从 UI 线程以外的线程“触摸” UI 元素,因此在调用 Console.ReadLine() 后,您需要使用 @ 987654323@ 或 Control.BeginInvoke 在 UI 中进行更改。

    此外,您当前正在声明一个名为a局部变量,但从未为Program.a 赋值。

    这是一个完整的版本:

    using System;
    using System.Threading;
    using System.Windows.Forms;
    
    class Program
    {
        private Program()
        {
            // Actual form is created in Start...
        }
    
        private void StartAndLoop()
        {
            Label label = new Label { Text = "Nothing" };
            Form form = new Form { Controls = { label } };
            new Thread(() => Application.Run(form)).Start();
            // TODO: We have a race condition here, as if we
            // read a line before the form has been fully realized,
            // we could have problems...
    
            while (true)
            {
                string line = Console.ReadLine();
                Action updateText = () => label.Text = line;
                label.Invoke(updateText);
            }
       }
    
        static void Main(string[] args)
        {
            new Program().StartAndLoop();
        }
    }
    

    【讨论】:

      【解决方案2】:

      你的代码有很多问题,我不会包括命名选择。

      • Application.Run 正在阻塞。在您的 Form 关闭之前,您的其余代码不会被调用。

      • 你递归调用lol(),我不建议这样做。请改用while 循环。

      • 您正试图从与创建控件的线程不同的线程设置Label 的文本。您将需要使用Invoke 或类似方法。

      这是您的代码可能的完整示例。我试图修改尽可能少的东西。

      class Program
      {
          static Label a;
      
          static void Main(string[] args)
          {
              var t = new Thread(ExecuteForm);
              t.Start();
              lol();
          }
      
          static void lol()
          {
              var s = Console.ReadLine();
              a.Invoke(new Action(() => a.Text = s));
              lol();
          }
      
          public static void ExecuteForm()
          {
              var abc = new Form();
              a = new Label();
              a.Text = "nothing";
              abc.Controls.Add(a);
              Application.Run(abc);
          }
      }
      

      【讨论】:

        【解决方案3】:

        您是在创建新的Thread 之前生成表单。这意味着在退出 Form 之前,您的程序永远不会真正创建新的 Thread

        你需要使用

        System.Threading.Thread t = new System.Threading.Thread(Program.lol);
        t.Start();
        Application.Run(abc);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-05-12
          • 2023-03-31
          • 1970-01-01
          相关资源
          最近更新 更多