繁体   English   中英

显示Windows窗体时,控制台应用程序不接受输入

[英]Console application does not accept input when a windows form is displayed

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

码:

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();
        }


    }
}

Application.Run将阻塞,直到窗体关闭。 因此,您应该在单独的线程上调用

但是,您的UI然后将在该单独的线程上执行-并且您不得“触摸”来自UI线程以外的其他线程的UI元素,因此在调用Console.ReadLine() ,您将需要使用Control.InvokeControl.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();
    }
}

您的代码中有很多问题,我将不包括命名选择。

  • 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);
    }
}

在创建新的Thread之前,您将生成表格。 这意味着在退出Form之前,您的程序实际上不会创建新的Thread

您需要使用

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM