c# - How to wait for a return value from an event handler without blocking main UI thread -
so have method uses library generate external webpage allow user enter facebook credentials verification. upon entering creating profile based on user's account , saving database. once save database expecting boolean represent whether or not account unique. need way wait database complete of work before continuing execution.
i've tried several different methods including doing work on new thread (which won't work since ui needs on main thread) using autoresetevent
wait auth.completed
event fire. when using block thread , not present our external webpage user.
whats making more complicated trying deal different events without getting ahead of ourselves. first need wait auth.completed
fire, inside event need wait asynchronous request.getresponseasync().continuewith<task<bool>>(async t => ...
event finish, , wait database complete task , somehow push return value way calling procedure.
as of right now, code perform desired functions, return false since aren't waiting of events fire.
public bool loginfacebook(bool islinkedaccount) { #if __ios__ uikit.uiwindow window = uikit.uiapplication.sharedapplication.keywindow; uikit.uiviewcontroller viewcontroller = window.rootviewcontroller; #endif var auth = new oauth2authenticator( clientid: "***********", scope: "email", authorizeurl: new uri("https://m.facebook.com/dialog/oauth/"), redirecturl: new uri("http://www.facebook.com/connect/login_success.html") ); #if __android__ forms.context.startactivity(auth.getui(android.app.application.context)); #elif __ios__ if (viewcontroller != null) { while (viewcontroller.presentedviewcontroller != null) viewcontroller = viewcontroller.presentedviewcontroller; viewcontroller.presentviewcontroller(auth.getui(), true, null); } #endif // if authorization succeeds or canceled, .completed fired. auth.allowcancel = true; auth.completed += (sender, eventargs) => { #if __ios__ viewcontroller.dismissviewcontroller(true, null); #endif if (eventargs.isauthenticated) { var request = new oauth2request("get", new uri("https://graph.facebook.com/me"), null, eventargs.account); request.getresponseasync().continuewith<task<bool>>(async t => { if (t.isfaulted) console.writeline("error: " + t.exception.innerexception.message); else { try { string content = t.result.getresponsetext(); console.writeline(content); jobject user = jsonconvert.deserializeobject<jobject>(content); facebook profile = new facebook(); profile.uuid = user["id"].tostring(); profile.firstname = user["first_name"].tostring(); profile.lastname = user["last_name"].tostring(); profile.email = user["email"].tostring(); profile.url = user["link"].tostring(); //get picture profile.photo = "https://graph.facebook.com/" + profile.uuid + "/picture?type=large"; if (!islinkedaccount) { //app.animateloading(loadingimage, overlayimage, loadingmessage); return await databaseinstance.insertsocialprofile(socialnetworks.facebook, profile, true); } else { await databaseinstance.linksocialaccounttoprofile(app.userprofile, profile, socialnetworks.facebook); return true; } } catch (exception e) { console.writeline(e.tostring()); } } return false; }); } }; return false; }
you can use taskcompletionsource
represent awaitable task, negotiate between event handler , rest of async
method.
for brevity , clarity, i've trimmed #ifdef
code example, focusing on core. in mind, here's like:
public async bool loginfacebook(bool islinkedaccount) { var auth = new oauth2authenticator( clientid: "***********", scope: "email", authorizeurl: new uri("https://m.facebook.com/dialog/oauth/"), redirecturl: new uri("http://www.facebook.com/connect/login_success.html") ); // if authorization succeeds or canceled, .completed fired. auth.allowcancel = true; taskcompletionsource<bool> completionsource = new taskcompletionsource<bool>(); auth.completed += (sender, eventargs) => { completionsource.setresult(eventargs.isauthenticated); }; if (!(await completionsource.task)) { return false; } var request = new oauth2request("get", new uri("https://graph.facebook.com/me"), null, eventargs.account); var t = await request.getresponseasync(); if (t.isfaulted) { console.writeline("error: " + t.exception.innerexception.message); return false; } try { string content = t.result.getresponsetext(); console.writeline(content); jobject user = jsonconvert.deserializeobject<jobject>(content); facebook profile = new facebook(); profile.uuid = user["id"].tostring(); profile.firstname = user["first_name"].tostring(); profile.lastname = user["last_name"].tostring(); profile.email = user["email"].tostring(); profile.url = user["link"].tostring(); //get picture profile.photo = "https://graph.facebook.com/" + profile.uuid + "/picture?type=large"; if (!islinkedaccount) { return await databaseinstance.insertsocialprofile(socialnetworks.facebook, profile, true); } else { await databaseinstance.linksocialaccounttoprofile(app.userprofile, profile, socialnetworks.facebook); return true; } } catch (exception e) { console.writeline(e.tostring()); return false; } }
naturally, change of method async
method, caller can wait asynchronously on result, avoiding blocking of main thread.
of course, lacking a good, minimal, complete code example start with, above browser-edited code. did not compile it, never mind test it. above general idea. assume can incorporate concept in actual code.
Comments
Post a Comment