animation - wpf is it possible to block ui thread while animating? -
folks, came across problem when going show off daughter power of wpf animation on resolving hanoi problem. problem related codes below:
void moveset(disk[] disks, int maxindex, char from, char via, char to) { if (maxindex > 0) moveset(disks, maxindex - 1, from, to, via); moveone(disks[maxindex], from, to); if (maxindex > 0) moveset(disks, maxindex - 1, via, from, to); } the above codes move disks recursively. , added animation in moveone method this:
void moveone(disk disk, char from, char to) { // set animation parameters ... upanimation... ... levelshiftanimation... ... downanimation... storyboard.settarget(upanimation, disk); storyboard.settarget(levelshiftanimation, disk); storyboard.settarget(downanimation, disk); storyboard.begin(disk); } the above codes work good. animations run @ same time. after few unordered animations disks changed position. looks not cool. want show animation of each disk 1 one. modified moveone method , made such changes:
void moveone(disk disk, char from, char to) { ... storyboard.settarget(upanimation, disk); storyboard.settarget(levelshiftanimation, disk); storyboard.settarget(downanimation, disk); autoresetevent signaler=new autoresetevent(false); eventhandler eh = null; eh = (s, e) => { storyboard.completed -= eh; signaler.set(); }; storyboard.completed+=eh; storyboard.begin(disk); signaler.waitone(); } the above modifications made whole program stuck. think cause both animation , moveone method running in 1 ui thread, blocking moveone method blocks animation. tried create , start(using ui dispatcher invoke) animation in newly created task, didn't work yet. @ last, had straighten real demands. want run 1 animation , block other animations , of them run on same sole ui thread. seems contradictory. don't know whether have wrong understanding. and, there solution occasion?
you wrap execution of storboard in task , await task.
this described in this answer. basically, subscribe completed event of storyboard. can await result. (code adopted provided link).
public static class storyboardextensions { public static task beginasync(this storyboard storyboard, frameworkcontentelement element) { system.threading.tasks.taskcompletionsource<bool> tcs = new taskcompletionsource<bool>(); if (storyboard == null) tcs.setexception(new argumentnullexception()); else { eventhandler oncomplete = null; oncomplete = (s, e) => { storyboard.completed -= oncomplete; tcs.setresult(true); }; storyboard.completed += oncomplete; storyboard.begin(element); } return tcs.task; } } in case, need is, replace call of storyboard.begin(disc); in moveon-method await storyboard.beginasync(disc);.
with change, turn event-based approach (using completed event) awaitable task makes handling easier.
Comments
Post a Comment