c# - How to postpone execution until some event happens? -
i have webbrowser control , has invokescript method, should call after webbrowser loaded.
so i've tried this:
private readonly manualreseteventslim browserloaded = new manualreseteventslim(false); private void browserloaded(object sender, navigationeventargs navigationeventargs) { browserloaded.set(); } private async task<object> invokescript(string invoke, object[] parameters = null) { return await task.factory .startnew(() => { if (!browserloaded.wait(timespan.fromseconds(10))) { throw new exception("timeout waiting browser load."); } }) .continuewith(task => parameters == null ? browser.invokescript(invoke) : browser.invokescript(invoke, parameters), taskscheduler.fromcurrentsynchronizationcontext()); }
it not nice me, works ok when called asynchronously. problem appears, when try read result value synchronously - app hangs:
private string getenteredtext() { return (string)invokescript("getenteredtext").result; }
i know, should go way async, i'm wondering properties:
public override string usertext { { return getenteredtext(); } set { setenteredtext(value); } }
or async wrong way go in case @ all?
update
property 'glue' between input field value in browser's page , view model in wpf, don't see way make separate methods, because part of bigger framework (notice override keyword on it). once browser control loaded, execute logic should not take long, guess less 10 milliseconds, why ok sync execution in case. , browser control loads fast enough, reason here delay make sure invokescript not called before load, not because taking long time or smth.
app hangs
we'll, said yourself. know why happens. you're blocking on call using task.result
, causes deadlock.
or async wrong way go in case @ all?
we don't have async properties. reason don't have them because properties aren't asynchronous nature. stephan cleary describes nicely:
if “property” needs asynchronously evaluated every time it’s accessed, you’re talking asynchronous operation.the best solution change property async method. semantically, shouldn’t property.
instead of property, make asynchronous method can await
properly.
in regards using manualresetevent
, use taskcompletionsource<bool>
instead. works "nicer" tpl:
private taskcompletionsource<bool> tcs = new taskcompletionsource<bool>(); private void browserloaded(object sender, navigationeventargs navigationeventargs) { tcs.trysetresult(true); } private async task<object> invokescript(string invoke, object[] parameters = null) { var timeouttask = task.delay(timespan.fromseconds(10)); if (timeouttask == await task.whenany(tcs.task, timeouttask)) { // you've timed out; } return task.run(() => { parameters == null ? browser.invokescript(invoke) : browser.invokescript(invoke, parameters) }); }
i see used taskscheduler.fromcurrentsynchronizationcontext()
in continuation. if need execute on ui thread, there no point in using threadpool thread @ all.
@noseratio adds webbrowser
sta object. answer here might help.
Comments
Post a Comment