How do I update a WPF control from a TPL task?

How do I update a WPF control from a TPL task?

Ok, so I tried some scripting to use the Dispatcher, but it gives an error anyway. I need help guys!

private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        //Application.Current.Dispatcher.Invoke((Action)MyInit); 
        backgroundDBTask = Task.Factory.StartNew(() =>
            {
                DoSomething1();
            }, TaskCreationOptions.LongRunning);
        backgroundDBTask.ContinueWith((t) =>
        {
            // ... UI update work here ...
        },             
        TaskScheduler.FromCurrentSynchronizationContext());             
    }

    void DoSomething1()
    {
        // MyInit();
        int number = 0;
        while (true)
        {
            if (state)
            {
                Thread.Sleep(1000);
                Console.WriteLine("Begin second task... {0}", number++);
               // mostCommonWords = GetMostCommonWords(words) + string.Format("   Begin second task... {0}", number++);

                textBox2.Text = (number++).ToString(); // Gives the error

                Dispatcher.BeginInvoke(); // How it should be ?
            }
        }
    }

      

Thank!

+2


source to share


2 answers


You need to pass the delegate that does your work to BeginInvoke

.
BeginInvoke

will run this delegate asynchronously on the UI thread.

For example:



Dispatcher.BeginInvoke(new Action(delegate {
    textBox2.Text = number.ToString(); 
}));

      

+5


source


I know there is already an answer and what Slaks gave you will fix it, as it will use the Dispatcher thread, so it won't throw an exception for accessing a control from a different thread

.

But I notice it.

 backgroundDBTask = Task.Factory.StartNew(() =>
        {
            DoSomething1();
        }, TaskCreationOptions.LongRunning);

      

With the help of this



 backgroundDBTask.ContinueWith((t) =>
    {
        // ... UI update work here ...
    },             
    TaskScheduler.FromCurrentSynchronizationContext());   

      

You already have a comment where to update the UI and you gave it too SynchronizationContext

. Why are you still trying to update UI

inside yours DoSomething1

?

If your goal Task

is to update UI

then there is no need to use ContinueWith

. Instead, just pass SynchronizationContext

it and it should work without an explicit call Dispatcher.BeginInvoke

.

backgroundDBTask = Task.Factory.StartNew(() =>
        {
            DoSomething1();
        },
    CancellationToken.None,
    TaskCreationOptions.None,
    TaskScheduler.FromCurrentSynchronizationContext()); 

      

+3


source







All Articles