How to update a WPF Control from the TPL Task?

强颜欢笑 提交于 2019-12-11 01:33:33

问题


How to update a WPF Control from the TPL Task?

Fine so I tried some scenarios to use Dispatcher but anyway it gives the error. 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 you!


回答1:


You need to pass a delegate that does your work to BeginInvoke.
BeginInvoke will asynchronously run this delegate on the UI thread.

For example:

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



回答2:


I know there is already an answer here and what Slaks gave you will fix it since it will use the Dispatcher thread thus will not throw an exception for accessing a control from a different thread.

But, I notice this.

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

With this

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

You already have a comment where to update the UI and you also gave it the SynchronizationContext. Why are you still trying to update the UI inside of your DoSomething1?

Unless your purpose of your Task is to update the UI then there is no need to use the ContinueWith. Instead just pass the SynchronizationContext and it should work without having to explicitly call the Dispatcher.BeginInvoke.

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


来源:https://stackoverflow.com/questions/7726697/how-to-update-a-wpf-control-from-the-tpl-task

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!