c# - Async Await to Keep Event Firing -
i have question async\await in c# .net app. i'm trying solve problem in kinect based application me illustrate, i've crafted analogous example:
imagine have timer, called timer1 has timer1_tick event set up. now, action take on event update ui current date time.
private void timer1_tick(object sender, eventargs e) { txttimervalue.text = datetime.now.tostring("hh:mm:ss.fff", cultureinfo.invariantculture); }
this simple enough, ui updates every few hundredths of seconds , can happily watch time go by.
now imagine want calculate first 500 prime numbers in same method so:
private void timer1_tick(object sender, eventargs e) { txttimervalue.text = datetime.now.tostring("hh:mm:ss.fff", cultureinfo.invariantculture); list<int> primenumberslist = workoutfirstnprimenumbers(500); printprimenumberstoscreen(primenumberslist); } private list<int> workoutfirstnprimenumbers(int n) { list<int> primenumberslist = new list<int>(); txtprimeanswers.clear(); int counter = 1; while (primenumberslist.count < n) { if (determineifprime(counter)) { primenumberslist.add(counter); } counter++; } return primenumberslist; } private bool determineifprime(int n) { (int = 2; < n; i++) { if (n % == 0) { return false; } } return true; } private void printprimenumberstoscreen(list<int> primenumberslist) { foreach (int primenumber in primenumberslist) { txtprimeanswers.text += string.format("the value {0} prime \r\n", primenumber); } }
this when experience problem. intensive method calculates prime numbers blocks event handler being run - hence timer text box updates every 30 seconds or so.
my question is, how can resolve while observing following rules:
- i need ui timer textbox smooth before, pushing intensive prime number calculation different thread. guess, enable event handler run before because blocking statement no longer there.
- each time prime number calculation function finishes, it's result written screen (using printprimenumberstoscreen() function) , should started again, in case prime numbers change of course.
i have tried things async/await , making prime number calculation function return task> haven't managed resolve problem. await call in timer1_tick event still seems block, preventing further execution of handler.
any gladly appreciated - i'm @ accepting correct answers :)
update: grateful @sstan able provide neat solution problem. however, i'm having trouble applying real kinect-based situation. little concerned making question specific, have posted follow new question here: kinect frame arrived asynchronous
so want start task without waiting result. when task has finished calculating should update ui.
first things async-await, later answer
the reason ui isn't responsive during long action because didn't declare event handler async. easiest way see result of creating event handler button:
synchronous - ui blocked during execution:
private void button1_clicked(object sender, eventargs e) { list<int> primenumberslist = workoutfirstnprimenumbers(500); printprimenumberstoscreen(primenumberslist); }
asynchronous - ui responsive during execution:
private async void button1_clicked(object sender, eventargs e) { list<int> primenumberslist = await task.run( () => workoutfirstnprimenumbers(500)); printprimenumberstoscreen(primenumberslist); }
note differences:
- the function declared async
- instead of calling function, task started using task.run
- the await statement makes sure ui-thread returns , keeps handling ui requests.
- once task finished, ui thread continues next part of await.
- the value of await return of workoutfirstnprimenumber function
note:
- normally you'll see async functions return task instead of void , task
<tresult
> instead of tresult. - the await task void , await task
<tresult
> tresult. - to start function separate task use task.run ( () => myfunction(...))
- the return of task.run awaitable task.
- whenever want use await, you'll have declare function async, , return task or task
<tresult
>. - so callers have async , forth.
- the async function may return void event handler.
your problem: timer tick reported when calculations still busy
the problem timer faster calculations. want if new tick reported when previous calculations not finished
- start new calculations anyhow. might lead lot of threads doing calculations @ same time.
- ignore tick until no calculations busy
- you choose let 1 task calculations , start them finished. in case calculations run continuously
(1) start task, not await it.
private void button1_clicked(object sender, eventargs e) { task.run ( () => { list<int> primenumberslist = workoutfirstnprimenumbers(500); printprimenumberstoscreen(primenumberslist); }); }
(2) ignore tick if task still busy:
task primecalculationtask = null; private void button1_clicked(object sender, eventargs e) { if (primecalculationtask == null || primecalculationtask.iscompleted) { // previous task finished. stat new 1 task.run ( () => { list<int> primenumberslist = workoutfirstnprimenumbers(500); printprimenumberstoscreen(primenumberslist); }); } }
(3) start task calculates continuously
private void starttask(cancellationtoken token) { task.run( () => { while (!token.iscancelrequested) { list<int> primenumberslist = workoutfirstnprimenumbers(500); printprimenumberstoscreen(primenumberslist); } }) }
Comments
Post a Comment