i've written loop in xamarin android load 10 images asynchronously using system.net.http.httpclient
. initiating 10 requests executes instantly, i'm not getting any continuation before 10 responses completed - 5 7 seconds later. why not responses coming individually, asynchronously?
i don't know how threads handled in xamarin might doing wrong. should not call ui thread? there way can specify scheduler or threading policy httpclient?
the code load function:
// method called 10 times in foreach loop, initated ui thread, not awaited private async void loadasync(string uri) { bitmap bitmap = await imgsvc.loadanddecodebitmap(uri); image.setimagebitmap(bitmap); } public async task<bitmap> loadanddecodebitmap(string uri) { var client = new httpclient(); byte[] data = await client.getbytearrayasync(uri); bitmap img = bitmapfactory.decodebytearray(data, 0, data.length); return img; }
link full solution
you should consider loading them @ same time using task.whenall
. creating multiple instance of httpclient
can have negative effects on performance.
first updating call avoid using async void
.
articleteaserview.cs
public async task setmodel(articleteaser model) { title.settext(model.promotioncontent.title.value, textview.buffertype.normal); description.settext(model.promotioncontent.description.value, textview.buffertype.normal); try { var uri = android.net.uri.parse(model.promotioncontent.imageasset.urls[0].url); log.debug(tag, "image " + (++ctr) + " load starting..."); await loadasync(model.promotioncontent.imageasset.geturlwithminheight(240), image); log.debug(tag, "image " + ctr + " load completed"); } catch (exception ex) { log.debug(tag, ex.message); } } static imagesvc imgsvc = new imagesvc(); //should consider injecting service private async task<image> loadasync(string uri, imageview image) { bitmap bitmap = await imgsvc.loadanddecodebitmap(uri); image.setimagebitmap(bitmap); } //use 1 shared instance of `httpclient` life of application private static httpclient client = new httpclient(); public async task<bitmap> loadanddecodebitmap(string uri) { byte[] data = await client.getbytearrayasync(uri); bitmap img = bitmapfactory.decodebytearray(data, 0, data.length); return img; }
finally assuming have collection of urls. create tasks , invoke of them @ same time.
mainactivity.cs
private event eventhandler loaddata = delegate { }; protected override void oncreate(bundle bundle) { base.oncreate(bundle); // set our view "main" layout resource setcontentview (resource.layout.main); initviews(); loaddata += ondataloading; // subscribe event loaddata(this, eventargs.empty); // raise event } //async void allowed on event handlers (actual event handler) //*oncreate* not event handler. based method. private async void ondataloading(object sender, eventargs e) { loaddata -= ondataloading; await loaddataasync(); } private void initviews() { //... } private async task loaddataasync() { var svc = new newsservice(); var promcontent = svc.syncloadstrong(); await bindview(promcontent); } private async task bindview(articlelist list) { log.debug(tag, "binding mainactivity"); viewgroup scroller = findviewbyid<viewgroup>(resource.id.scroller); if (list != null) { var tasks = new list<task>(); foreach (articleteaser teaser in list) { var atv = new articleteaserview(this, null); tasks.add(atv.setmodel(teaser)); scroller.addview(atv); } await task.whenall(tasks); } }
make sure not mixing blocking calls .result
, .wait()
async/await calls , avoid using async void
unless event handler.
Comments
Post a Comment