【问题标题】: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);