我目前正在开发一个应用程序,需要利用表单来阻止用户使用主表单几秒钟。尽管在主线程上运行代码似乎没问题,但弹出窗体上的标签在表单首次出现时不会呈现大约一秒钟。我认为如果我在一个单独的线程上运行该表单,渲染会更顺畅。渲染现在非常流畅,渲染后表格立即消失。计时器设置为五秒钟,屏幕上的标签倒计时。这是调用新线程和表单的相关代码:
System::Void MainScreen::runGame(int playerTurn) {
Thread ^ t = gcnew Thread(gcnew ThreadStart(gcnew MainScreen(),
&MainScreen::showModalDialog));
t->Start();
t->Join();
InitializeDice();
startTimer();
}
System::Void MainScreen::showModalDialog() {
GetReady ^ gr = gcnew GetReady();
gr->showModalPopup();
}
以下是表单中的代码:
public:
GetReady(void)
{
InitializeComponent();
}
System::Void showModalPopup() {
this->Show();
startTimer();
}
private: System::Void timerPrep_Tick(System::Object^ sender, System::EventArgs^ e) {
ts = ts->Subtract(TimeSpan(0, 0, 1));
if (ts->TotalSeconds <= 0) {
finishTimer();
} else {
lblTimer->Text = ts->ToString("mm\\:ss");
}
}
System::Void startTimer() {
array<String ^>^ minSec = gcnew array<String ^>(2);
minSec = lblTimer->Text->Split(':');
ts = gcnew TimeSpan(0, Convert::ToInt32(minSec[0]), Convert::ToInt32(minSec[1]));
Thread::Sleep(900);
timerPrep->Start();
}
System::Void finishTimer() {
timerPrep->Stop();
lblTimer->Text = "GO!!!";
Thread::Sleep(900);
this->Close();
}
我理想的解决方案是使用线程生成新表单,这样主表单和弹出表单中的呈现都很流畅。
我尝试过的事情:
如果您对我需要做什么有任何想法,以便为两种表格进行平滑渲染,请告诉我。谢谢!
答案 0 :(得分:1)
问题是showModalPopup使用 Show 方法而不是 ShowDialog 。线程启动,显示表单(它不阻止执行),启动计时器,结束并加入主线程。创建表单的线程已经完成,而winforms多线程问题就在这里。
首先启动计时器,然后使用 ShowDialog 显示模态窗口。像这样:
System::Void showModalPopup()
{
startTimer();
this->ShowDialog();
}
答案 1 :(得分:1)
在工作线程上显示UI充满了陷阱和惊喜。你在这里遇到的主要问题是线程不会引发消息循环。首先要求确保窗口可以接收Windows消息并确保线程不会立即终止。除了Jairo建议使用ShowDialog()之外,样板解决方案是:
System::Void MainScreen::showModalDialog() {
Application::Run(gcnew GetReady);
}
还有更多,显示窗口的线程应始终是STA线程。 COM的实现细节,需要获取剪贴板,拖放和shell对话框正常运行等内容:
Thread ^ t = gcnew Thread(gcnew ThreadStart(this, &MainScreen::showModalDialog));
t->SetApartmentState(ApartmentState::STA);
t->Start();
并且您通常在主线程上显示的窗口存在Z顺序问题。你的窗口令人讨厌的习惯消失在主线所拥有的窗口后面。没有好的解决方案。