c# - Keep UI responsive using Tasks, Handle AggregateException -
i have problem handling aggregateexception if winforms application starts task keep responsive while task performing.
the simplified case follows. suppose form has slow method, instance:
private double slowdivision(double a, double b) { system.threading.thread.sleep(timespan.fromseconds(5)); if (b==0) throw new argumentexception("b"); return / b; }
after pressing button want form show result of slowdivision(3,4). following code hang user interface time:
private void button1_click(object sender, eventargs e) { this.label1.text = this.slowdivision(3, 4).tostring(); }
hence i'd start task processing. when task finishes, should continue action display result. prevent invalidoperationexception need sure label1 accessed thread created on, hence control.invoke:
private void button1_click(object sender, eventargs e) { task.factory.startnew ( () => { return this.slowdivision(3, 4); }) .continuewith( (t) => { this.invoke( new methodinvoker(() => { this.label1.text = t.result.tostring(); })); }); }
so far, good, how handle exceptions, instance if want calculate slowdivision(3, 0)?
normally if task throws unhandled exception, forwarded waiting thread via aggregateexception. numerous examples show following code:
var mytask = task.factory.startnew ( () => ...); try { mytask.wait(); } catch (aggregateexception exc) { // handle exception }
the problem is: can't wait task execute, because want ui remain responsive.
create task continuation on faulted read task.exception , handle accordingly doesn't work:
private void button1_click(object sender, eventargs e) { var slowdivtask = task.factory.startnew(() => { return this.slowdivision(3, 0); }); slowdivtask.continuewith((t) => { this.invoke(new methodinvoker(() => { this.label1.text = t.result.tostring(); })); }, taskcontinuationoptions.notonfaulted); slowdivtask.continuewith((t) => { aggregateexception ae = t.exception; ae.handle(exc => { // handle exception return true; }); }, taskcontinuationoptions.onlyonfaulted); }
a try / catch in function doesn't (as expected).
so how react on aggregateexceptions thrown task without waiting it.
if can use .net 4.5
, use newer async/await
, simplifies code lot, , saves having deal continuations , aggregateexception
s, create noise in code , distract focusing on trying accomplish.
it this:
private async void button1_click(object sender, eventargs e) { try { double result = await task.run(() => this.slowdivision(3, 0)); this.label1.text = result.tostring(); } catch (exception ex) { this.textbox1.text = ex.tostring(); } } private double slowdivision(double a, double b) { system.threading.thread.sleep(timespan.fromseconds(5)); if (b == 0) throw new argumentexception("b"); return / b; }
Comments
Post a Comment