Avoiding the window (WPF) to freeze while using TPL

為{幸葍}努か 提交于 2019-12-03 21:19:53

You will have to create and open the connection for this command within the Task's body. Either that or don't close the connection outside the Task, which I assume is what you're doing here, but can't tell from the one line of code you pasted.

I would personally do it all inside the Task body. Why should the user have to wait for you to even get the connection/command setup if they don't have to? Also there's the chance that you connection is a shared instance and that won't work across threads.

Once you get the DB work into a Task it will be executed on a Thread Pool thread by default which will free up the WPF dispatcher thread to go back to processing UI events preventing the "freezing". Most likely you will want to update the UI after that DB task has completed and to do that you would hpjust add a continuation task, but in order to be able to manipulate the UI from that continuation task you need to make sure it's explicitly scheduled to run on the Dispatcher thread. This is done by explicitly specifying a TaskScheduler for the current synchronization context while scheduling the continuation. That would look something like this:

Task backgroundDBTask = Task.Factory.StartNew(() =>
{
    ... DB work here ...
});

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

The magic here is the use of the TaskScheduler::FromCurrentSynchronizationContext method which will schedule the continuation to be executed on the Dispatcher thread of the current call.

In addition to @Drew Marsh answer,

To avoid Exception:

The current SynchronizationContext may not be used as a TaskScheduler

You can use check for Synchronization Content Exists:

private static TaskScheduler GetSyncronizationContent() => 
     SynchronizationContext.Current != null ? 
          TaskScheduler.FromCurrentSynchronizationContext() : 
          TaskScheduler.Current;

And use it instead:

Task backgroundDBTask = Task.Factory.StartNew(() =>
{
    //... DB work here ...
});

backgroundDBTask.ContinueWith((t) =>
{
    //... UI update work here ...
},
GetSyncronizationContent());
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!