asp.net web api - Background workers in WebApi -


i'm trying figure out how comes request api call waiting backgroundworkers completed.

this jobmanager:

public class jobmanager { public list<abstractjob> jobs;  public jobmanager() {   jobs = new list<abstractjob>(); }  public int newtestjob() {   var job = new testjob();   job.name = "testjob";   jobs.add(job);   return job.id; }  public void startjob(int id) {   var job = jobs.where(j => j.id == id).firstordefault();   if (job == null) throw new exception("not found");    job.execute(); }  public string statusjob(int id) {   var job = jobs.where(j => j.id == id).firstordefault();   if (job == null) throw new exception("not found");    return job.status; }  public list<abstractjob> runningjobs() {   return jobs.where(j => j.status == "running").tolist(); } } 

this ijob

public interface ijob {   void execute(); }   

this abstractjob

public abstract class abstractjob : ijob {   static int counter = 0;   protected backgroundworker _bw = new backgroundworker();   public int id;   public string status;   public string name;    public abstractjob() {     interlocked.increment(ref counter);     id = counter;     _bw.workerreportsprogress = true;     _bw.workersupportscancellation = true;     _bw.dowork += new doworkeventhandler(bw_dowork);     _bw.progresschanged += new progresschangedeventhandler(bw_progresschanged);     _bw.runworkercompleted += new runworkercompletedeventhandler(bw_runworkercompleted);     _bw.reportprogress(0, "idle");   }    public virtual string describe() {     return "not known 4 legged animal!";   }    public void execute() {     _bw.runworkerasync();   }   private void bw_progresschanged(object sender, progresschangedeventargs e) {     this.status = e.userstate.tostring();   }    private void bw_runworkercompleted(object sender, runworkercompletedeventargs e) {     backgroundworker worker = sender backgroundworker;     if ((e.cancelled == true)) {       this.status = "canceled";     } else if (!(e.error == null)) {       this.status = "error";      } else {       this.status = "done";     }   }   public abstract void bw_dowork(object sender, doworkeventargs e); } 

and job:

public class testjob : abstractjob {   public override void bw_dowork(object sender, doworkeventargs e) {     system.threading.thread.sleep(50000); // representing actual code takes time   } } 

so wanted in controller create 10 jobs , return id's while tasks running in background.

public ienumerable<int> get() {   var ids = new list<int>();   (int = 0; < 10; i++) {     var id = jobm.newtestjob();     jobm.startjob(id);     ids.add(id);   }    return ids; } 

this seem work great, except request waiting on sleeptimer in job. although when place breakpoint on return ids in controller; hit's fast (so async working)

normally should have message: "an asynchronous module or handler completed while asynchronous operation still pending." it considered dangerous launch background tasks without awaiting them

you should use taskparallellibrary - async/await do , wait tasks return:

 public async task get()         {             var tasks = new list<task>();             (int = 0; < 10; i++)             {                 tasks.add(task.run(() =>                 {                    //your code here                 }));             }             await task.whenall(tasks);         } 

if doing fireandforget can use new queuebackgroundworkitem framework 4.5.2.

also check out post. better use native async methods , transform whole chain async instead of doing "task.run".


Comments