c# - How to make sure a loop within a task has run at least once -


let's have class called scheduler contains dictionary of <userid, task>, task continuously loops , updates internal dictionary schedules user <userid, schedule> information database i.e. want keep information updated in real time.

i want have method on scheduler class getscheduleforuser checks see if there task user , if not it'll create task wait til finishes , retrieves schedules user (lazy load it).

my question is, after first iteration of task i'll have schedule available , can retrieve schedule...no problem first iteration need wait until task finished @ least 1 time before retrieving schedule.

i can start task , create while loop until flag set when it's finished first time loop seems me there better way , it'll useful first iteration. afterwards schedule available , won't need functionality.

does have clean way accomplish this?

the best solution can think of use taskcompletionsource, eser mentioned in comment. here's rough code sample lots of console output make easier follow it's doing. added idisposable scheduler calss , dictionary of cancellationtokensource that, when you're done scheduler, can stop of tasks.

using system; using system.collections.generic; using system.linq; using system.threading; using system.threading.tasks;  public class program {     // helper property simplify console output     public static string timestring { { return datetime.now.tostring("mm:ss.fff"); } }      public static void main(string[] args)     {         using (var scheduler = new scheduler())         {             var userid = "1";              console.writeline(timestring + " main: getting schedule first time...");             var sched1 = scheduler.getscheduleforuser(userid);             console.writeline(timestring + " main: got schedule: " + sched1);              console.writeline(timestring + " main: waiting 2 seconds...");             system.threading.thread.sleep(2000);              console.writeline(timestring + " main: getting schedule second time...");             var sched2 = scheduler.getscheduleforuser(userid);             console.writeline(timestring + " main: got schedule: " + sched2);         }          console.writeline();         console.writeline("press key end . . .");         console.readkey();     } }  public class scheduler : idisposable {     // helper property simplify console output     public static string timestring { { return datetime.now.tostring("mm:ss.fff"); } }      private dictionary<string, task> tasksdictionary { get; set; }     private dictionary<string, taskcompletionsource<bool>> taskcompletionsourcesdictionary { get; set; }     private dictionary<string, cancellationtokensource> cancellationtokensourcesdictionary { get; set; }     private dictionary<string, string> schedulesdictionary { get; set; }      public scheduler()     {         tasksdictionary = new dictionary<string, task>();         taskcompletionsourcesdictionary = new dictionary<string, taskcompletionsource<bool>>();         cancellationtokensourcesdictionary = new dictionary<string, cancellationtokensource>();         schedulesdictionary = new dictionary<string, string>();     }      public void dispose()     {         if (tasksdictionary != null)         {             if (cancellationtokensourcesdictionary != null)             {                 foreach (var tokensource in cancellationtokensourcesdictionary.values)                     tokensource.cancel();                  task.waitall(tasksdictionary.values.toarray(), 10000);                  cancellationtokensourcesdictionary = null;             }              tasksdictionary = null;         }          cancellationtokensourcesdictionary = null;         schedulesdictionary = null;     }      public string getscheduleforuser(string userid)     {         // there's schedule,         if (schedulesdictionary.containskey(userid))         {             console.writeline(timestring + "     getschedule: had schedule user " + userid);             return schedulesdictionary[userid];         }          // if there's no task yet, start 1         if (!tasksdictionary.containskey(userid))         {             console.writeline(timestring + "     getschedule: starting task user " + userid);             var tokensource = new cancellationtokensource();             var token = tokensource.token;             taskcompletionsourcesdictionary.add(userid, new taskcompletionsource<bool>());             var task = (new taskfactory()).startnew(() => generateschedule(userid, token, taskcompletionsourcesdictionary[userid]), token);             tasksdictionary.add(userid, task);             cancellationtokensourcesdictionary.add(userid, tokensource);             console.writeline(timestring + "     getschedule: started task user " + userid);         }          // if there's task running, wait         console.writeline(timestring + "     getschedule: waiting first run complete user " + userid);         var temp = taskcompletionsourcesdictionary[userid].task.result;         console.writeline(timestring + "     getschedule: first run complete user " + userid);          return schedulesdictionary.containskey(userid) ? schedulesdictionary[userid] : "null";     }      private void generateschedule(string userid, cancellationtoken token, taskcompletionsource<bool> tcs)     {         console.writeline(timestring + "         task: starting task userid " + userid);          bool firstrun = true;         while (!token.iscancellationrequested)         {             // simulate work while building schedule             if (token.waithandle.waitone(1000))                 break;              // update schedule             schedulesdictionary[userid] = "schedule set @ " + datetime.now.toshorttimestring();             console.writeline(timestring + "         task: updated schedule userid " + userid);              // if first run, set result taskcompletionsource             if (firstrun)             {                 tcs.setresult(true);                 firstrun = false;             }         }          console.writeline(timestring + "         task: ended task userid " + userid);     } } 

here's fiddle show in action: .net fiddle


Comments

Popular posts from this blog

java - nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet Hibernate+SpringMVC -

sql - Postgresql tables exists, but getting "relation does not exist" when querying -

asp.net mvc - breakpoint on javascript in CSHTML? -