Why is my user interface blocked when using the System.Threading.Task class this way?

In my ViewModel, I have this code:

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

wtih Log is a very simple class with several public properties.

According to my understanding of the Task class, the mainModel GetLogs () function, called in this way, should be run in a separate thread, and while it is retrieving records from the database, my user interface should respond, however this is not what happens, but instead of this record retrieved from the data store, my user interface is blocked.

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

EDIT: my underestimation of the Task class was incomplete, using the ContinueWith method of the Task class ensured that async was executed, as described below in member responses ...

+3
source share
3 answers

This is because you are calling Resultimmediately after starting the asynchronous operation. The property getter Resultblocks the execution of the current thread until the task completes.

Update:

To get the result asynchronously, you need to call ContinueWithand specify the function that will be called when the task is completed:

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

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

The access receiver for this property ensures that the asynchronous operation is completed before returning. As soon as the calculation result is available, it will be saved and will be immediately returned on subsequent calls to the result.

, .

+2

Assuming mainModel.GetLogs is thread safe, you probably want something like this that calls GetLogs in the background thread, and then only sets Logs to the result, when it ends, the logs end. TaskScheduler.FromCurrentSynchronizationContext () ensures that this part is executed in the user interface thread, which is required if your user interface is bound to this collection.

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

All Articles