我有这样的东西:
void ClickHandler() // Called from several places
{ // Try to prevent queuing accidental extra clicks during lengthy operation
GetMainWindow().IsEnabled = false; // "GetMainWindow()" you know what I mean
DoLengthyStuffInThisThread(); // Yes, I know I shouldnt
PresentResult();
GetMainWindow().IsEnabled = true;
}基本上就是这样。不过要澄清的是:
即使我设置了IsEnabled = false,它也没有达到预期的效果,我的额外点击会在操作过程中发生。(如果我返回时没有恢复该值,则会产生影响。)我假设正常情况下我的线程需要返回才能使禁用生效,但我不希望创建额外的线程。
发布于 2013-07-09 23:01:12
感谢大家的回答。最好的答案实际上是在威尔·埃丁斯的一部*comments,中。额外的thanks!*
对我这个令人难以置信的问题的回答是:System.Windows.Forms.Application.DoEvents();
虽然不是很好看,但这是我不得不做的。孩子们,不要在家里尝试!
public void WrapLengthyWork(Action lengthyWork)
{
SetWaiting(true);
System.Windows.Forms.Application.DoEvents();
lengthy();
SetWaiting(false);
}
public void SetWaiting(bool wait)
{
if (wait == true)
{
Mouse.OverrideCursor = Cursors.Wait;
Application.Current.MainWindow.IsEnabled = false;
}
else
{
IsEnabled = true;
Mouse.OverrideCursor = Cursors.Arrow;
}
}另外,对于所有建议我正确使用线程切换的人:也感谢你们。我(正如我提到的)痛苦地意识到上述代码片段是糟糕的编码风格。我的问题是"LengthyWork()“本身充满了引用回图形用户界面的东西,并且必须在图形用户界面线程中运行,例如:
while(stuffToDo)
{
Fetch();
Calculate();
UpdateGUI();
}考虑到强加的时间限制(几个小时)和有限的任务(“防止在处理过程中点击,并显示等待-光标和触摸没有其他”),不幸的是,适当的解决方案不是一个选择。
发布于 2013-07-09 02:19:49
你必须将冗长的工作转移给另一个线程。直到封闭方法完成之后,UI才会收到此更改的通知(因此,没有机会使用布局通道刷新其状态)。
我可以想象,在这个冗长的方法中发生的任何事情都是在操作UI上显示的一些数据。如果您正在使用数据绑定,此操作将在后台填充UI (如果它在后台线程上运行),然后当该操作完成时,它可以告诉UI重新启用自身。
这是半伪代码,但请查看Task.Factory.StartNew和Dispatcher.BeginInvoke。
public void ClickHandler()
{
MainWindow.IsEnabled = false;
Task.Factory.StartNew(() =>
{
// Length work goes here
}).ContinueWith((result) =>
{
Dispatcher.BeginInvoke(() =>
{
MainWindow.IsEnabled = true;
});
});
}发布于 2013-07-09 02:25:38
@william-custode是对的,你应该在主应用程序线程上做繁重的工作。但是,解决方法是在开始"DoLengthyStuffInThisThread“之前使用forcing the window's message loop to consume all currently dispatched messages。
https://stackoverflow.com/questions/17533352
复制相似问题