locked
ASYNC TASKS

    Question

  • I developed the following little program to test async operations; this is the complete code, however you can find it also at: https://onedrive.live.com/redir?resid=DD81C6C8181B3CF5%21105

        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
                mmm.progr1 = new Progress<int>(p => loopPB1.Value = p);
                mmm.progr2 = new Progress<int>(p => loopPB2.Value = p);
                mmm.msg = new Progress<string>(s => AddMessage(s));
            }

            string messages = "";
            static MMM mmm = new MMM();

            void AddMessage(string msg)
            {
                messages += "\n" + msg;
                msgTB1.Text = messages;
            }

            private void Break_Click(object sender, RoutedEventArgs e)
            {
                AddMessage("Break");
                mmm.Break();
            }

            private void Task1_Click(object sender, RoutedEventArgs e)
            {
                messages = "Task1 - reset";
                msgTB1.Text = messages;
                loopPB1.Value = 0;
                loopPB2.Value = 0;

                mmm.Start1();
                AddMessage("Task1 - after Run");
            }

            private void Task2_Click(object sender, RoutedEventArgs e)
            {
                mmm.Start2();
                AddMessage("Task2 - after Run");
            }
        }

        public class MMM
        {
            bool abort;
            Task loopTask;
            public IProgress<int> progr1;
            public IProgress<int> progr2;
            public IProgress<string> msg;

            public void Break()
            {
                abort = true;
            }

            public void Start1()
            {
                loopTask = Task.Factory.StartNew(Loop1);
            }

            public async void Start2()
            {
                if (loopTask == null) throw new Exception("loopTask is null");
                else if (loopTask.Status == TaskStatus.Running)
                {
                    if (msg != null) msg.Report("Awaiting Loop1");
                    await Task.Delay(10);   // without this delay the message displays after the Wait
                    loopTask.Wait();
                }
                if (msg != null) msg.Report("Starting Loop2");
                await Task.Run(() => Loop2());
                if (msg != null) msg.Report("Start2 completed");
            }

            // === task implementations

            void Loop1()
            {
                if (msg != null) msg.Report("Loop1 started");
                abort = false;
                for (int i = 0; i < 100; i++)
                {
                    if(progr1 != null) progr1.Report(i);
                    if (abort)
                    {
                        if (msg != null) msg.Report("Loop1 aborted");
                        return;
                    }
                    for (int j = 0; j < 10000000; j++) ;     // just an await loop
                }
                if (msg != null) msg.Report("Loop1 completed");
            }

            void Loop2()
            {
                if (msg != null) msg.Report("Loop2 started");
                abort = false;
                for (int i = 0; i < 100; i++)
                {
                    if (progr2 != null) progr2.Report(i);
                    if (abort)
                    {
                        if (msg != null) msg.Report("Loop2 aborted");
                        return;
                    }
                    for (int j = 0; j < 10000000; j++) ;     // just an await loop
                }
                if (msg != null) msg.Report("Loop2 completed");
            }
        }

    (The task implementations and relevant commands are in a separate class - this is a requirement of the actual code where this piece will go.)

    I click Task1, then Task2 to start these tasks.
    The idea is that Task2 awaits for Task1 to be completed before starting.

    When I let Task1 complete its job, the ProgressBar 'progr1' works normally; however, if I click Task2 before Task1 is completed, hence entering loopTask.Wait(), it stops advancing during the wait, and it will jump directly to 100% at the end of Task1. ProgressBar 'progr2' works perfectly as expected.

    Obviously I would like that 'progr1' continues to advance smoothly regardless of whether Task2 is awaiting or not.
    Any suggestion?

    Thursday, May 8, 2014 11:38 AM

Answers

All replies

  • Hi, you can use Task.ContinueWith to start task2 when task2 is finish:

    http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.continuewith(v=vs.110).aspx

    for example:

    else if (loopTask.Status == TaskStatus.Running)
    {
        lookTask.ContinueWith((antecedent) =>
                    {
                         if (msg != null) msg.Report("Starting Loop2");
                await Task.Run(() => Loop2());
                if (msg != null) msg.Report("Start2 completed");
                    });
           return;
    }

    • Marked as answer by GiorgioITA Thursday, May 8, 2014 4:10 PM
    Thursday, May 8, 2014 1:49 PM
  • Excellent! ... with minor corrections:

    - the compiler does not want the 'await' in your snippet;

    - your snippet fails to start Task2 if I click the button after Task1 is completed, I simply removed the 'else if (...)':

            public async void Start2()
            {
                if (loopTask == null) throw new Exception("loopTask is null");
                loopTask.ContinueWith((antecedent) =>
                    {
                        if (msg != null) msg.Report("Starting Loop2");
                        Task.Run(() => Loop2());
                        if (msg != null) msg.Report("Start2 completed");
                    });
            }

    Now everything works fine!

    Thank you very much for your help.

    Thursday, May 8, 2014 4:14 PM