开发者

Why is my UI blocked when using System.Threading.Task class this way?

开发者 https://www.devze.com 2023-03-05 00:28 出处:网络
In my ViewModel I have this code: Logs = new ObservableCollection<Log>(); Logs = Task.Factory.StartNew(() => mainModel.GetLogs()).Result;

In my ViewModel I have this code:

Logs = new ObservableCollection<Log>();
Logs = Task.Factory.StartNew(() => mainModel.GetLogs()).Result;

wtih Log being a very simple class with a couple of public properties.

According to my understanding of Task class the mainModel function GetLogs() invoked this way should run on a separate thread and while it is fetching records from the database my UI should be responsive, however that is not what is happening, instead while records are being fetched from the data store my UI is blocked.

I was hoping someone could explain why... TIA.

EDIT: My understading of the Tas开发者_开发技巧k class was incomplete, using ContinueWith method of the Task class will ensure the async execution as explained below in member replies...


This is because you call Result right after you started the asynchronous operation. The getter of the Result property blocks the execution of current thread until the task is completed.

Update:

In order to get the result asynchronously, you need to call ContinueWith and specify a function that will be called when the task is completed:

Task.Factory.StartNew(() => mainModel.GetLogs()).ContinueWith(t => Logs = t.Result);


You should not use the Result property like this i think, from MSDN:

The get accessor for this property ensures that the asynchronous operation is complete before returning. Once the result of the computation is available, it is stored and will be returned immediately on later calls to Result.

It makes the current thread wait if you access it while the task is running.


Assuming mainModel.GetLogs is threadsafe you probably want something like this, which calls the GetLogs on a background thread, and then only sets Logs to the result when it finished gettings the logs. The TaskScheduler.FromCurrentSynchronizationContext() ensures that execution of that part is run on the UI thread, which will be required if your UI is bound to that collection.

Task doStuff = Task.Factory.StartNew<ICollection>(() =>
    {
        return mainModel.GetLogs();
    })
    .ContinueWith((result) =>
    {
        Logs = result;
    }, TaskScheduler.FromCurrentSynchronizationContext());
0

精彩评论

暂无评论...
验证码 换一张
取 消