Wpf application crashes when using BackgroundWorker

my view model creates a BackgroundWorker in its constructor. BackgroundWorker updates the model properties from the DoWork event handler. The code below is a contrived example (ViewModelBase is taken almost verbatim from MVVM paper).


public class MyViewModel : ViewModelBase
{
    public int MyProperty
    {
        get
        {
            return this.my_property;
        }
        private set
        {
            if (this.my_property != value)
            {
                this.my_property = value;
                this.OnPropertyChanged("MyProperty");
            }
        }
    }

    public MyViewModel()
    {
        this.worker = new BackgroundWorker();
        this.worker.DoWork += (s, e) => { this.MyProperty = 1; };
        this.worker.RunWorkerAsync();
    }
}

my view is tied to this view model:


public partial class MyPage : Page
{
    public MyPage()
    {
        InitializeComponent();
        this.DataContext = new MyViewModel();
        }
}

The problem is that my application is periodically reset when my page is displayed. this definitely has something to do with workflow and data binding in XAML. it seems that if I run the worker from within the Loaded event handler for the page, the problem will disappear, but since it is difficult to play it sequentially, I'm not sure if this fix is ​​correct.

- - , ?

EDIT: , . - InvalidOperationException, ShowDialog, . .

+3
5

MyProperty , , .

  • (, lock)

  • , .

, . , BackgroundWorker :

public void MyViewModel()
{
    this.worker = new BackgroundWorker();
    this.worker.DoWork += (s, e) => { /* do something */ e.Result = 1; };
    this.worker.RunWorkerCompleted += (s, e) =>
    {
        // all of this happens back in the UI thread
        if (e.Error != null)
        {
            // do some error handling... some exception occurred during DoWork
        }
        else
        {
            this.MyProperty = (int)e.Result;
        }
    };
    this.worker.RunWorkerAsync();
}
+3

, / XAML . invokde Dispatcher :

:

Dispatcher.BeginInvoke(delegate()
{
//UI element (test.Text) being updated with value i.ToString() from background thread
test.Text += i.ToString();
});
}
+3

INotifyPropertyChanged.PropertyChanged INotifyCollectionChanged.CollectionChanged ( ObservableCollection) WPF.

, Dispatcher.Invoke RunWorkerCompleted ( ), DoWork.

+1

I think the problem was that I was updating my properties from the DoWork handler. after I moved the updates to the ProgressChanged handler, the problem seems to be gone. I can even now update an ObservableCollection from within ProgressChanged. therefore, it seems that the ProgressChanged event handler automatically starts in the user interface thread.

0
source

Source: https://habr.com/ru/post/1768119/


All Articles