WPF:从后台线程更新 UI 的问题

标签 wpf multithreading

我的代码启动了一个后台线程。后台线程进行更改并希望主线程中的 UI 更新。启动线程然后等待的代码如下所示:

                Thread fThread = new Thread(new ThreadStart(PerformSync));

                fThread.IsBackground = true;
                fThread.Start();

                fThread.Join();

                MessageBox.Show("Synchronization complete");

当后台想要更新 UI 时,它会设置一个 StatusMessage 并调用下面的代码:
    static StatusMessage _statusMessage;
    public delegate void AddStatusDelegate();
    private void AddStatus()
    {
        AddStatusDelegate methodForUIThread = delegate
        {
            _statusMessageList.Add(_statusMessage);
        };

        this.Dispatcher.BeginInvoke(methodForUIThread, System.Windows.Threading.DispatcherPriority.Send);
    }

_statusMessageList 是一个 ObservableCollection,它是 ListBox 的源。

AddStatus 方法被调用,但主线程上的代码从不执行——也就是说,_statusMessage 不会在线程执行时添加到 _statusMessageList。但是,一旦完成(fThread.Join() 返回),主线程上的所有堆叠调用都会被执行。

但是,如果我在调用 fThread.Start() 和 fThread.Join() 之间显示一个消息框,则状态消息会正确更新。

我需要更改什么以便在等待线程终止时执行主线程中的代码(UI 更新)?

谢谢。

最佳答案

fThread.Join导致您的主线程阻塞,直到后台线程完成。只要主线程被阻塞,UI就无法更新。

你需要做的是这样的事情(未经测试,但你应该明白):

void someUiEventThatCausesTheBackgroundProcessingToStart() {
    Thread fThread = new Thread(new ThreadStart(PerformSync));
    fThread.IsBackground = true;

    // disable some UI components here, so that the user cannot
    // start the thread a second time
    ...

    fThread.Start();

    // *don't* call Thread.Join here, so that your main thread does not block!
}

void PerformSync() {
    try {
        // do your stuff here
        ...
    } finally {
        Dispatcher.Invoke(new Action(ProcessingDone));
    }
}

void ProcessingDone() {
    // re-enable the UI components
    ...

    MessageBox.Show("Synchronization complete");
}

当然,在 WPF 中,禁用/启用 UI 组件最好使用一些 IsBusyProcessing与相关 UI 元素的触发器绑定(bind)的依赖属性,但这是另一个故事......

编辑:作为另一种选择,您可能想要 check out BackgroundWorker类,其中包含 ProgressChangedRunWorkerCompleted在主线程中自动触发的事件。

关于WPF:从后台线程更新 UI 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2859750/

相关文章:

.net - 在 Expression Blend 中反转剪切路径

WPF 用户控件 : Have a Command that is only available internally in the UserControl

c++ - 从另一个任务创建任务 - 用线程池库替换 std::async 时出现死锁

c# - 在立即窗口中调用C#方法VS,得到 'System.Threading.ThreadAbortException'

c# - 安排要发送的电子邮件

c# - 如何为绑定(bind)正确设置 WPF UserControl

.net - WPF 进度条中的颜色错误

c++ - 使用 std::mutex 时遇到问题

c# - 使用 C# 学习多线程的资源

java - 在 Swing 事件中启动线程