如何在WPF上使用Dispatcher或BackroundWorker以及自定义StatusBar控件

时间:2021-08-07 09:20:42

In my application I realized a custom statusbar control. It has progressbar, statusTextBox etc. Other modules could get the instance of that class with MEF, and bind their data in his elements with methods and properties. The problem is that the View of my statusbar updates only after some operation has finished. Here is a code example:

在我的应用程序中,我实现了自定义状态栏控件。它有progressbar,statusTextBox等。其他模块可以使用MEF获取该类的实例,并使用方法和属性将其数据绑定在他的元素中。问题是我的状态栏的视图仅在某些操作完成后才更新。这是一个代码示例:

[ImportingConstructor]
public IconManagerModel(IStatusBar statusBar)
{
    StatusBar = statusBar;
}

public void SomeMethod()
{    
    for(...)
    {
        //I tried to use Dispatcher but it didn't help. View updates after method has finished
        Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Normal,  
            delegate()
            {
                StatusBar.SetProgress(amountComleted,total)
            }
        );

        // ...
    }
}

Thanx

2 个解决方案

#1


1  

You want to run SomeMethod() on another thread, then call back onto the Dispatcher to update the progress. Really, if the custom progress bar is hooked up to some UI element, then the implementation should handle the calling back onto the UI thread.

您想在另一个线程上运行SomeMethod(),然后回调到Dispatcher以更新进度。实际上,如果自定义进度条连接到某个UI元素,那么实现应该处理回调到UI线程。

You may want something a little like:

你可能想要一些类似的东西:

public IconManagerModel(IStatusBar statusBar)
{
    StatusBar = statusBar;

    var thread = new Thread(new ThreadStart(SomeMethod));
    thread.Start();
}

SomeMethod() will now be running on a different thread, so if you update the progress on the UI thread then you should see the results you desire.

SomeMethod()现在将在不同的线程上运行,因此如果您更新UI线程上的进度,那么您应该看到所需的结果。

#2


0  

To add to the above answer by slade, I'd also suggest using DispatcherPriority.Render if you want the message pump to process the message immediately. Play around with Invoke (synchronous) and BeginInvoke (asynchronous). The former will force the update immediately, however will block your processing work. The latter will update when the message pump is free and is generally recommended.

要通过slade添加上述答案,如果您希望消息泵立即处理消息,我还建议使用DispatcherPriority.Render。使用Invoke(同步)和BeginInvoke(异步)。前者将立即强制更新,但会阻止您的处理工作。后者将在消息泵空闲时更新,通常建议使用。

Either way your background work needs to be on a background thread, particularly if it is lengthy or it will block your UI for the duration.

无论哪种方式,您的后台工作都需要在后台线程上,特别是如果它很长或者它会在一段时间内阻止您的UI。

#1


1  

You want to run SomeMethod() on another thread, then call back onto the Dispatcher to update the progress. Really, if the custom progress bar is hooked up to some UI element, then the implementation should handle the calling back onto the UI thread.

您想在另一个线程上运行SomeMethod(),然后回调到Dispatcher以更新进度。实际上,如果自定义进度条连接到某个UI元素,那么实现应该处理回调到UI线程。

You may want something a little like:

你可能想要一些类似的东西:

public IconManagerModel(IStatusBar statusBar)
{
    StatusBar = statusBar;

    var thread = new Thread(new ThreadStart(SomeMethod));
    thread.Start();
}

SomeMethod() will now be running on a different thread, so if you update the progress on the UI thread then you should see the results you desire.

SomeMethod()现在将在不同的线程上运行,因此如果您更新UI线程上的进度,那么您应该看到所需的结果。

#2


0  

To add to the above answer by slade, I'd also suggest using DispatcherPriority.Render if you want the message pump to process the message immediately. Play around with Invoke (synchronous) and BeginInvoke (asynchronous). The former will force the update immediately, however will block your processing work. The latter will update when the message pump is free and is generally recommended.

要通过slade添加上述答案,如果您希望消息泵立即处理消息,我还建议使用DispatcherPriority.Render。使用Invoke(同步)和BeginInvoke(异步)。前者将立即强制更新,但会阻止您的处理工作。后者将在消息泵空闲时更新,通常建议使用。

Either way your background work needs to be on a background thread, particularly if it is lengthy or it will block your UI for the duration.

无论哪种方式,您的后台工作都需要在后台线程上,特别是如果它很长或者它会在一段时间内阻止您的UI。