我正在研究C#/ .NET 3.5 / Windows Forms程序。我想创建一个无模式对话框,然后使用从主窗体生成的信息更新它。我已经找到了另一个方向的几个例子 - 来自对话框的信息更新了主窗口,但是我在反方向上遇到了麻烦。对话框中的GUI无法正常运行。鼠标光标是沙漏。我有时会看到更新,但我经常会看到一个坚固的白色框,一次在对话框顶部的其他窗口的残余,或者它冻结。
最终,对话框将显示更复杂的信息,但是现在我只是想复制一个在主窗口上显示为标签的计数器。要启动对话框,我执行以下操作:
bool secondWindowOpen = false;
Thread secondWindowThread;
MyPopupWindow secondWindow;
delegate void TextBoxDelegate(string message);
private void buttonPop_Click(object sender, EventArgs e)
{
// If the second window is not open, then open it
if (!secondWindowOpen)
{
secondWindowOpen = true;
secondWindow = new MyPopupWindow();
secondWindowThread = new Thread(secondWindow.MyMethod);
secondWindowThread.Start();
}
else // Close the second window
{
secondWindowOpen = false;
secondWindow.ShouldStop = true;
secondWindowThread.Join();
}
}
我使用以下代码更新计数器:
if (secondWindow != null)
{
secondWindow.CounterText = args.FrameNumber.ToString();
}
用于控制“无模式”对话框的代码如下所示。我承认设置文本字段的代码可能是错误的,但这是我目前工作的最好的事情(调用调用给我带来了麻烦)。
public partial class MyPopupWindow : Form
{
public MyPopupWindow()
{
InitializeComponent();
}
public bool ShouldStop
{
get { return shouldStop; }
set { shouldStop = value; }
}
private bool shouldStop = false;
public void MyMethod()
{
this.Show();
this.Refresh();
while (!shouldStop)
{
Thread.Sleep(100);
labelCounter.Text = CounterText;
Refresh();
}
this.Close();
}
public string CounterText;
}
我的主要问题如下:当只需要更新自己的GUI元素时,将无模式对话框放入第二个线程的最佳方法是什么?从主窗口/线程更新这些GUI元素的最佳方法是什么?谢谢!
答案 0 :(得分:1)
表单的工作方式是,如果程序是一个处理消息并将它们传递给要处理的表单的循环,那么核心就是核心。如果您的表单永远不会将控制权返回到您的消息循环,您的程序将无法正常工你试图通过添加更多线程来解决这个问题,但这种方式导致了它自己的痛苦。
您无法在线程中执行此操作,因为应用于表单的所有操作必须在UI线程上完成。 你可以使用BeginInvoke将像Invalidate之类的调用传递回UI线程,但是这真的很麻烦 - 编写在一个UI线程上运行的协作窗口比触发大量线程更好,然后尝试将UI线程推入为他们做事。
要执行此操作,您将创建表单,然后将控制权返回给您的消息处理循环。在将来的某个时间,您将从按钮单击等事件关闭窗口。如果您需要根据任何事件更新窗口,您可以在事件处理程序中调用invalidate然后返回。
答案 1 :(得分:0)
根据Jason的建议,我最终简化了事情并让它真正发挥作用。
首先,当我显示第二个窗口时,不再启动新线程。相反,我会做以下事情:
bool secondWindowOpen = false;
MyPopupWindow secondWindow;
private void buttonPop_Click(object sender, EventArgs e)
{
// If the second window is not open, then open it
if (!secondWindowOpen)
{
secondWindowOpen = true;
secondWindow = new MyPopupWindow();
secondWindow.Show();
}
else // Close the second window
{
secondWindowOpen = false;
secondWindow.Close();
}
}
然后我将第二个窗口中的代码简化为以下内容:
public partial class MyPopupWindow : Form
{
public MyPopupWindow()
{
InitializeComponent();
}
public string CounterText
{
set { labelCounter.Text = value; }
}
}
答案 2 :(得分:0)
首先,请为我的英语道歉,因为我是法国人。
然后,如果我理解你的问题,你想从第一个表格更新第二个表格的控件。
请使用表格的Tag对象。
从第一个表单创建第二个表单的实例,如下所示:
Form2 f = new Form2();
f.Tag = MyDataObject();
显示表格
f.Show() => Modeless way
或f.ShowDialog => Modal way
在Form2的构造函数中,您可以使用Tag对象更新控件:
public Form2()
{
MyDataObject do = (MyDataObject)this.Tag;
MyLabel.Text = do.LabelText;
}
如果您想从Form2到主表单,请执行相同的操作:
进入Form2
this.Tag = MyDataObject;
this.Close();
进入主表格:
`MyDataObject do = (MyDataObject)f2.Tag;`
我知道这个话题很老但希望这有帮助