1

I have something like this:

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;  
}

That's it basically. To clarify though:

Even though I have set IsEnabled = false it does not have the desired effect, my extra clicks go through during the operation. (It does have an effect if I return without restoring the value.) I assume that normally my thread needs to return in order for the disabling to to have effect but I'd rather not create an extra thread.

4

3 回答 3

2

您必须将冗长的工作转移到另一个线程。直到封闭方法完成后,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-08T18:19:48.630 回答
0

谢谢大家的回答。最佳答案实际上是 Will Eddins 的其中一条*评论。额外感谢!*

我丑陋的问题的丑陋答案是: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()”本身充满了引用回 GUI 并且必须在 GUI 线程中运行的东西,例如:

while(stuffToDo)
{
    Fetch();
    Calculate();
    UpdateGUI();
}

鉴于强加的时间限制(几个小时)和有限的任务(“防止在处理过程中点击并显示等待光标并且什么都不碰”),不幸的是,正确的解决方案不是一个选项。

于 2013-07-09T15:01:11.527 回答
-1

@william-custode 是对的,您应该在主应用程序线程上完成繁重的工作。但是,一种变通方法是强制窗口的消息循环在开始“DoLengthyStuffInThisThread”之前使用所有当前分派的消息。

于 2013-07-08T18:25:37.723 回答