WPF - 从不同的线程更新主窗口

时间:2014-09-03 10:14:51

标签: c# wpf multithreading

通常当有人想要执行一些长时间运行的任务并将其进度报告给UI时,在更新UI时,在新线程中调用长时间运行的任务。 我希望做一个更舒适的方法,例如:

MainWindow.SetWatingMsg("please wait ...");

doLongRunnnigTask();

MainWindow.RemoveWaitingMsg();

因此,在这种情况下,应该在与运行长时间运行任务的线程不同的线程中更新UI。 我已经尝试了这个,在我的主窗口中我有一个带有进度条动画的隐藏视图框。在我的应用程序中,我有一个对我的主窗口的引用,所以我的计划是在代码中从不同的地方调用以下函数:

public void SetWaitMsg(string msg)
{
    if (Session.User != null)
        if (Session.User.Configuration.DontShowWaitMsg)
            return;

    Task.Factory.StartNew(() =>
    {
        AppMainWindow.Dispatcher.BeginInvoke(DispatcherPriority.Render, (System.Action)delegate()
        {
            AppMainWindow.pleaseWaitBox.Visibility = Visibility.Visible;
        });
    });
}

public void RemoveWaitMsg()
{
    Task.Factory.StartNew(() =>
    {
        AppMainWindow.Dispatcher.BeginInvoke(DispatcherPriority.Render, (System.Action)delegate() { AppMainWindow.pleaseWaitBox.Visibility = Visibility.Collapsed; });
    });
}

问题是这不起作用,我没有错误,只是更新。 UI更新的唯一时间是在调用set和删除函数之间打开确认弹出窗口。

帮助将不胜感激。

由于

1 个答案:

答案 0 :(得分:0)

最好删除Task.Factory.StartNew()。但我觉得这不重要。看起来你正在UI线程上执行长时间运行的任务。我的意思是,为了让WPF播放动画,您需要在并行线程上执行操作,同时UI线程将播放您的动画。

因此,此代码用于设置来自任何线程的等待消息:

public void SetWaitMsg(string msg)
{
    if (Session.User != null)
        if (Session.User.Configuration.DontShowWaitMsg)
            return;

    AppMainWindow.Dispatcher.BeginInvoke(DispatcherPriority.Render, (System.Action)delegate()
    {
        AppMainWindow.pleaseWaitBox.Visibility = Visibility.Visible;
    });
}

public void RemoveWaitMsg()
{
    AppMainWindow.Dispatcher.BeginInvoke(DispatcherPriority.Render, (System.Action)delegate() { AppMainWindow.pleaseWaitBox.Visibility = Visibility.Collapsed; });
}

但是当Yuval帮助我意识到,我们不确定你是否正确地执行了后台任务。因此,假设您在UI线程上执行上面的代码,您的实际代码应如下所示:

MainWindow.SetWatingMsg("please wait ...");

Task.Factory.StartNew(() => doLongRunnnigTask());

MainWindow.RemoveWaitingMsg();


public void SetWaitMsg(string msg)
{
    if (Session.User != null && Session.User.Configuration.DontShowWaitMsg)
            return;

    AppMainWindow.pleaseWaitBox.Visibility = Visibility.Visible;
}

public void RemoveWaitMsg()
{
    AppMainWindow.pleaseWaitBox.Visibility = Visibility.Collapsed;
}