c# - wpf mvvm awaiting method blocks UI while simulating with await Task Delay doesn't -
when following ui doesn't freeze:
xaml binding:
<button command="{binding longrunningcommand}" />
viewmodel:
ctor { longrunningcommand = new delegatecommand<object>(processlongrunningcommand); } public delegatecommand longrunningcommand { get; private set; } private async void processlongrunningcommand(object e) { await task.delay(5000); }
but if replace task.delay real method ui freezes. weird. below example:
xaml binding:
<button command="{binding longrunningcommand}" />
viewmodel:
private readonly idbaccess _dbaccess; ctor(idbaccess dbaccess) { _dbaccess = dbaccess longrunningcommand = new delegatecommand<object>(processlongrunningcommand); } public delegatecommand longrunningcommand { get; private set; } private async void processlongrunningcommand(object e) { var callresult = await _dbaccess.longrunningmethod(); //adjust viewmodel observablecollection property binds listbox callresult }
dbaccess impl:
public task longrunningmethod(object e) { return task.run(() => { ... } }
can see i'm doing wrong please, lost lot of time on this...
and btw know async void
not best practice couldn't find solution make delegatecommand asynchronous.
edit
after more research concluded 'render' issue. longrunningcommand asynchronous rendering , binding taking time , blocks ui. have no idea how solve render issue.
this task awaiting deadlock caught me out long time too, until found solution.
replace
var callresult = await _dbaccess.longrunningmethod();
with
var callresult = await _dbaccess.longrunningmethod().configureawait(false);
see this blog post stephen cleary details why.
note continuation after await on different dispatcher context, directly updates ui (such populating observable collection) must marshalled ui dispatcher. many mvvm frameworks contain utilities - use dispatcherhelper class mvvm light.
if you're using resharper, there's plugin can install check configureawait() added every await statement.
Comments
Post a Comment