c# - Accessing Response Object While Using WebForms Async/Await -


i have simple .net 4.5 webforms project using output results of service checks. have created service checking classes multi-threaded , awaitable (each check might take 1-3 seconds , want them checked in parallel). want result of each service check written web page , flushed determined (i don't care if results in order). service checker methods have been tested , work fine in console application, i'm having trouble porting webforms app.

the code below works (very randomly). sometimes, it's perfect. other times, "skips" displaying results of 1 of tests. other times, mixes display of css style in results! mostly, though, crashes on response.flush line in checkservice stating "overlapped i/o operation in progress" , crashes.

how can write the web page response buffer when each check finishes , displays results in stable manner?

here's code aspx page...

<%@ page language="c#" async="true" autoeventwireup="true" inherits="servicemonitor._default" codebehind="default.aspx.cs" %> 

and here's code behind...

public partial class _default : system.web.ui.page {   protected void page_load(object sender, eventargs e)   {       response.write("<style type=\"text/css\">body {font-family: arial;font-size: 10pt;}</style>");       response.write("beginning processing...<br/>");       response.flush();       registerasynctask(new pageasynctask(checkservices));   }    protected async task checkservices()   {       response.write(string.format("starting checks @ {0}<br/>", datetime.now.tolongtimestring()));       var tasks = new list<task<servicestatus>>       {           task.run(() => checkservice("serviceone")),           task.run(() => checkservice("servicetwo")),           task.run(() => checkservice("servicethree"))       };       var checkresults = (await task.whenall(tasks)).tolist();       response.write(string.format("checking complete @ {0}<br/>", datetime.now.tolongtimestring()));       response.flush();   }    public servicestatus checkservice(string servicename)   {       var starttime = datetime.now;        // simulate longer running process, pausing 1-3 seconds       var random = new random();       var end = datetime.now + timespan.frommilliseconds(random.next(1000, 3000));        while (datetime.now < end) { }        var elapsedtime = (datetime.now - starttime).totalseconds;       var service = new servicestatus {name = servicename, isrunning = true};       response.write(string.format("done {0} in {1} seconds<br/>", service.name, elapsedtime.tostring("n2")));       response.flush();       return service;     } }  public class servicestatus {     public string name { get; set; }     public bool isrunning { get; set; } } 

fyi - app isn't supposed pretty, hence removal of standard html markup. won't accessed many users (really me) iis blocking isn't concern , page should return within 20-30 seconds.

your problem you're trying access request context (i.e., reponse.write) random background thread (i.e., task.run).

the ideal solution go async way. this, mean make service checkers asynchronous not multithreaded. if they're implemented using api ping, can check out httpclient implementation.

once they're asynchronous, checkservice method async well:

public async task<servicestatus> checkserviceasync(string servicename) {   var starttime = datetime.now;    // simulate longer running process, pausing 1-3 seconds   var random = new random();   var waittime = timespan.frommilliseconds(random.next(1000, 3000));   await task.delay(waittime);    var elapsedtime = (datetime.now - starttime).totalseconds;   var service = new servicestatus {name = servicename, isrunning = true};   response.write(string.format("done {0} in {1} seconds<br/>", service.name, elapsedtime.tostring("n2")));   response.flush();   return service; } 

and can called concurrently, without multithreading:

protected async task checkservicesasync() {   response.write(string.format("starting checks @ {0}<br/>", datetime.now.tolongtimestring()));   var tasks = new list<task<servicestatus>>   {     checkservice("serviceone"),     checkservice("servicetwo"),     checkservice("servicethree")   };   var checkresults = (await task.whenall(tasks)).tolist();   response.write(string.format("checking complete @ {0}<br/>", datetime.now.tolongtimestring()));   response.flush(); } 

Comments

Popular posts from this blog

java - How to specify maven bin in eclipse maven plugin? -

single sign on - Logging into Plone site with credentials passed through HTTP -

php - Why does AJAX not process login form? -