none
Tasks and reminders RRS feed

  • Question

  • Hi all,

    I created few reminders (a reminder to show user when to take out the trash) and every timer has his own task. So if I have 10 reminders, then I have 10 tasks.

    I could use Windows Scheduler or Quartz.net library, but I decided to use something else.

    I'm not sure if I did everything alright regarding disposing tasks, cancellation tokens etc.

    Appreciate your help

    using Terminal = System.Console;

    using Mischel.Synchronization;
    // taken from Jim Mischel
    // http://www.mischel.com/pubs/waitabletimer.zip

    public class Reminders { public int ReminderId { get; set; } public string ReminderTxtToRemind { get; set; } public DateTime DateWhenToExecute { get; set; } public Reminders(int id, string message, DateTime whenToExecute) { ReminderId = id; ReminderTxtToRemind = message; DateWhenToExecute = whenToExecute; } } class QueueTask { // vars for task mngmt // If I have more than one task, only one cancel token source is enough to cancel all tasks. public CancellationTokenSource CancelTokenSource = null; public CancellationToken CancelToken; public Task ExecutionTask = null; // I will put all tasks in a list public List<Task> TaskList; // for better control of time when reminder will be executed public WaitableTimer WaitTimer = null; // I will put all the times into public List<WaitableTimer> WaitTimerList; // for disposing a task bool IsTaskAborted { get; set; } #region Set Task Token, Cancellation Token and init Timer and Tasks list public QueueTask() { CancelTokenSource = new CancellationTokenSource(); CancelToken = CancelTokenSource.Token; WaitTimerList = new List<WaitableTimer>(); TaskList = new List<Task>(); } #endregion #region Send new Task to Task Factory public void Produce(Reminders reminder) { ExecutionTask = Task.Factory.StartNew(() => RunSched(reminder), CancelToken); IsTaskAborted = false; } #endregion #region Run action -> schedule next reminder public void RunSched(Reminders r) { // calculate time when to remind and run waitable time based upon diff variable long diff = 0; if (r.DateWhenToExecute < DateTime.Now) return; if (r.DateWhenToExecute > DateTime.Now) diff = Convert.ToInt64((r.DateWhenToExecute - DateTime.Now).TotalSeconds); // using Waitable Timer class from Jim Mischel // https://stackoverflow.com/questions/18611226/c-how-to-start-a-thread-at-a-specific-time // http://www.mischel.com/pubs/waitabletimer.zip WaitTimer = new WaitableTimer(true, TimeSpan.FromSeconds(diff), 0); WaitTimerList.Add(WaitTimer); while (!CancelToken.IsCancellationRequested) { try { if (CancelToken.IsCancellationRequested) Terminal.WriteLine("Cancel requested"); // timer here is waiting ... WaitTimer.WaitOne(); // When time is over, execute that reminder: Terminal.WriteLine(r.ReminderTxtToRemind + ". Started on thread: " + Thread.CurrentThread.GetHashCode()); } catch (OperationCanceledException e) { // supress exception // break; } finally { // When task is executed, then dispose a task DisposeTask(true); } } } #endregion #region Dispose current task public void DisposeTask(bool dispose) { //Terminal.WriteLine("Dispose triggered..."); try { if (!IsTaskAborted) { if (dispose) { CancelTokenSource.Cancel(); ExecutionTask.Wait(); CancelTokenSource.Dispose(); ExecutionTask.Dispose(); WaitTimerList.Remove(WaitTimer); } IsTaskAborted = true; } } catch (Exception ae) { // supress task //Terminal.WriteLine(ae); } finally { CancelTokenSource = null; ExecutionTask = null; } } #endregion } class Program { static void Main(string[] args) { // this is for testing purposes // Memory goes to roof and I'm not sure if task is really disposed, objects and so on... // Dunno if everything I done is alright. /* for (int i = 0; i < 100; i++) { Terminal.WriteLine("****\nStart of " + i + " test\n****"); Start(); Thread.Sleep(5000); Terminal.WriteLine("****\nEnd of " + i + " test\n"); }*/ // manual testing /* Start(); Terminal.WriteLine("Press a key..."); Terminal.ReadLine(); Start(); Terminal.WriteLine("Press a key..."); Terminal.ReadLine(); */ } #region Start engine static void Start() { // Here I create few reminders, then schedule reminders and trigger STOP of all tasks/schedules. // Create some reminders var reminderExamples = SetReminders(); // Then execute those reminders var qt = new QueueTask(); ExecuteReminders(reminderExamples, qt); // wait for background thread to initialize // and show reminder Thread.Sleep(2500); // after showing few reminders (not all) -> I will execute abort/cancel a task.. // Like I want to stop all. Terminal.WriteLine("We send cancel flag to task ..."); Stop(qt); } #endregion #region Set some reminders and save to list static List<Reminders> SetReminders() { var reminderExamples = new List<Reminders>(); var remind = new Reminders(1, "Throw Thrash", DateTime.Now.AddSeconds(1)); reminderExamples.Add(remind); remind = new Reminders(2, "Make Tea", DateTime.Now.AddSeconds(2)); reminderExamples.Add(remind); remind = new Reminders(3, "Drink Coffee", DateTime.Now.AddSeconds(3)); reminderExamples.Add(remind); remind = new Reminders(4, "Eat sth", DateTime.Now.AddSeconds(4)); reminderExamples.Add(remind); remind = new Reminders(5, "Eat Veggies", DateTime.Now.AddSeconds(5)); reminderExamples.Add(remind); return reminderExamples; } #endregion #region Method to execute reminders static void ExecuteReminders(List<Reminders> reminderExamples, QueueTask Qt) { foreach (var c in reminderExamples) { Qt.Produce(new Reminders(c.ReminderId, c.ReminderTxtToRemind, c.DateWhenToExecute)); } } #endregion #region Execute STOP of all tasks!! static void Stop(QueueTask Qt) { try { // If I want to cancel a task, there is no way until first cancel a timer. // Cancel first the timer foreach (var time in Qt.WaitTimerList) { time.Cancel(); } // Then cancel task(s). Qt.CancelTokenSource.Cancel(); foreach (var task in Qt.TaskList) { // just to be sure to dispose a task.. task.Dispose(); } } catch (Exception e) { // supress except //Terminal.WriteLine("Exception occured" + e); } } #endregion }




    Thursday, November 1, 2018 11:04 PM

Answers

  • Hi bobis123,

    As I know, the Dispose method would release all resources used by the current instance of the Task definitely.

    What is the version of your .net framework? If your app targets the .NET Framework 4.5 or later, there is no need to call Dispose unless performance or scalability testing indicates that, based on your usage patterns, your app's performance would be improved by disposing of tasks.

    I think memory goes up maybe caused by another reason. You could use Memory Usage tool to analyze the memory.

    For more details about the tool, please refer to the MSDN document.

    https://docs.microsoft.com/en-us/visualstudio/profiling/memory-usage-without-debugging2?view=vs-2017

    Best Regards,

    Wendy 


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by bobis123 Friday, November 9, 2018 8:39 AM
    Thursday, November 8, 2018 8:14 AM
    Moderator

All replies

  • Hi,

    thanks for posting here.

    >>I created few reminders (a reminder to show user when to take out the trash) and every timer has his own task. So if I have 10 reminders, then I have 10 tasks.
    I could use Windows Scheduler or Quartz.net library, but I decided to use something else.
    I'm not sure if I did everything alright regarding disposing tasks, cancellation tokens etc.

    Please provide more specific information about your issue. What's the type of your application? Have you faced any problems during your development? We couldn't help you well without detailed error information.

    Your understanding and cooperation will be grateful.

    Best Regards,

    Baron Bi


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, November 2, 2018 1:43 AM
    Moderator
  • Hi,

    application is written in C# - Console Application.

    I'm not sure, when I send cancellation token for the running task, is task really aborted and disposed?

    I'm not sure if task still runs in background. When I ran test using while loop, I watched how much memory consumes in task manager. And memory gets bigger for each loop. Task Id always gets incremented, ID is not the same, gets bigger each time, so I have to dispose something but don't know what.

    BR


    • Edited by bobis123 Friday, November 2, 2018 9:04 AM
    Friday, November 2, 2018 7:11 AM
  • Hi,

    Since your case is more related to c# code. I will move it to c# forum for better support.

    Your understanding and cooperation will be grateful.

    Best Regards,

    Baron Bi



    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, November 2, 2018 7:37 AM
    Moderator
  • Hi bobis123,

    If you want to release the thread without check whether the task is really aborted and disposed, you could try to use Thread pool.

    https://docs.microsoft.com/en-us/dotnet/api/system.threading.threadpool?view=netframework-4.7.2

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, November 6, 2018 7:35 AM
    Moderator
  • Thank you for proposal, but I would like to really abort and dispose a task and release a memory.

    Tuesday, November 6, 2018 8:21 AM
  • Hi bobis123,

    Task has Dispose method to release all resources used by the current instance of the Task.

    https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.dispose?view=netframework-4.7.2

    Here is a blog with dispose the task for your reference.

    https://blogs.msdn.microsoft.com/pfxteam/2012/03/25/do-i-need-to-dispose-of-tasks/

    Best Regards,

    Wendy


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, November 6, 2018 8:24 AM
    Moderator
  • Oh oh,

    I'm using dispose method and my question was: is task really disposed, because memory goes up after disposing.

    Tuesday, November 6, 2018 9:04 AM
  • Hi bobis123,

    As I know, the Dispose method would release all resources used by the current instance of the Task definitely.

    What is the version of your .net framework? If your app targets the .NET Framework 4.5 or later, there is no need to call Dispose unless performance or scalability testing indicates that, based on your usage patterns, your app's performance would be improved by disposing of tasks.

    I think memory goes up maybe caused by another reason. You could use Memory Usage tool to analyze the memory.

    For more details about the tool, please refer to the MSDN document.

    https://docs.microsoft.com/en-us/visualstudio/profiling/memory-usage-without-debugging2?view=vs-2017

    Best Regards,

    Wendy 


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    • Marked as answer by bobis123 Friday, November 9, 2018 8:39 AM
    Thursday, November 8, 2018 8:14 AM
    Moderator
  • I totally forgot about console..

    While text was adding in console, memory got bigger. That is the reason why memory went up every time. Thank you for feedback.

    Friday, November 9, 2018 8:43 AM