Pararell Task Library - Parallel.For freezing up

Hello, I'm testing a simple loop using the Task Parallel Library and Parallel.For.
However I'm having some difficulties making this to work. First, the UI will freeze until the loop is finished (cannot move the form around or click any other buttton s).
Therefore, I can't cancel the loop until it's done.

Any ideas on this? I've used a normal For loop and I can get the form to move while it's working but I can't cancel it.


 private CancellationTokenSource cancelToken = new CancellationTokenSource();


        private void button1_Click(object sender, EventArgs e)
        {
            Task.Factory.StartNew(() => {  WriteLog(); });  
        }

        private void WriteLog()
        {
            ParallelOptions po = new ParallelOptions();
            po.CancellationToken = cancelToken.Token;
            po.MaxDegreeOfParallelism = System.Environment.ProcessorCount;

            try
            {
                po.CancellationToken.ThrowIfCancellationRequested();
                Parallel.For(0, 1000, po, i =>
                {

                    po.CancellationToken.ThrowIfCancellationRequested();
                    txt_Log.Invoke((Action)delegate
                    {

                        txt_Log.AppendText("Line: " + i + "\n");

                    });

                });

                this.Invoke((Action)delegate
                {
                    this.Text = "Done";
                });
            }
           
            catch (OperationCanceledException ex)
            {
                this.Invoke((Action)delegate
               {
                   this.Text = ex.Message;
               });
              
            }
           
          
        }
      
        private void btnCancel_Click(object sender, EventArgs e)
        {
            cancelToken.Cancel();
        }
    }

Open in new window


Thanks
Adrian CrossAsked:
Who is Participating?
 
ambienceCommented:
You are confusing concurrency for asynchrony. Parallel extensions will only provide concurrency, i.e. ability to run task in parallel. This is still done synchronously which is why your UI is freezing.

In your case, its going to perform worse than a non-parallel (simple) for loop because the Invoke is to be called on the UI thread. Essentially you have now introduced contention for the UI resource (multiple threads trying to execute delegate on UI thread).

Either take away the parallelism; remove Invoke from parallel; or use backgroundworker or Tasks to perform the operation in an asynchronous manner.
0
 
louisfrCommented:
Each Invoke uses the form's thread. With a Parallel.For call there are so many of them that the thread has no time left to manage the form events.
To leave time for the events, you could put a call to Thread.Sleep after each Invoke call.
And put those two in a lock statement, because there's no way all parallel tasks are going to be in the Sleep call at the same time otherwise.
lock (syncObject)
{
    txt_Log.Invoke((Action)delegate
    {
        txt_Log.AppendText("Line: " + i + "\n");
    });
    Thread.Sleep(0);
}

Open in new window

0
 
Adrian CrossAuthor Commented:
Thanks. very helpful answers.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.