我还没有找到其他人有同样的问题,所以希望有人能有一些想法,或者能给我另一个答案。
当通过按下窗体上的按钮来运行函数时,另一个按钮应该可见。然而,按钮永远不会出现,即使它是功能中的第一件事。函数中的所有其他代码都能完美工作。
这是代码:
private void trackbar_Change(object sender, EventArgs e)
{
button.Visible = true;
progressbar.Visible = true;
...
progressbar.Visible = false;
button.Visible = false;
}
进度条显示并运行良好,函数中的所有其他代码也运行良好,但按钮根本不会显示。
如果我从函数末尾删除button.Visible = false;
,那么按钮确实会出现,但只有在执行完所有其他代码之后。像这样:
private void trackbar_Change(object sender, EventArgs e)
{
button.Visible = true;
progressbar.Visible = true;
...
progressbar.Visible = false;
//button.Visible = false;
}
注释掉那一行会导致按钮出现。现在,如果我在按钮行之后添加一个消息框,那么它也可以工作。
private void trackbar_Change(object sender, EventArgs e)
{
button.Visible = true;
MessageBox.Show("Button should be visible now");
progressbar.Visible = true;
...
progressbar.Visible = false;
button.Visible = false;
}
在按钮行之后添加消息框会使按钮在正确的时间出现。
有人知道这个按钮为什么会这样吗?
听起来GUI线程很忙。尝试通过调用Application.DoEvents()来强制屏幕更新,例如:
button.Visible = true;
progressbar.Visible = true;
Application.DoEvents();
DoEvents()
将强制处理消息队列中的所有消息。
更好的解决方案是移动主UI线程的长运行线程。使用BackgroundWorker执行任务。
这将使表单整体反应更灵敏。例如,你可以与表单交互,它不会变成"白色"。实现BackgroundWorker很简单,对于主UI线程上长时间运行的进程来说是必须的
问题是您正在UI线程上执行一个长时间运行的进程,因此在线程空闲之前不会将按钮设置为可见。但是,当线程空闲时,您已经将visible设置为false。
最好的方法是在后台工作程序上执行长时间运行的进程,这样UI线程就不会被阻塞。进度条工作的原因是它运行在不同的线程上。
还有另一种方法,但可能不太正确,那就是在将visible设置为true后对表单发出Refresh。
如果你需要BackgroundWorker的帮助,请告诉我,但这很直接。
运行Windows窗体时,它会创建新窗体,然后等待事件处理。每当表单处理一个事件时,它都会处理与该事件相关联的所有代码。所有其他事件都在队列中等待。当您的代码处理事件时,您的应用程序不会响应。例如,如果在顶部拖动另一个窗口,则不会重新绘制该窗口。
如果在代码中调用DoEvents,则应用程序可以处理其他事件。使用Application.DoEvents();
如果控件像面板一样位于容器内,并且当容器控件的可见性设置为false时,您试图更改控件的可见性,则会出现这种行为。