Parallel.For
-
Donnerstag, 8. März 2012 00:24
just a couple of quick questions.
1- when I use Parallel.For (or Parallel.Foreach) from say a button event, these are creating subthreads but the parallel threads are still considered part of the GUI thread which allows GUI to be updated (and the GUI is locked while the threads are live). Yes?
2- but when I use a Task to kick off the logic above, then the GUI is no locked, and I no longer have access to the GUI thread. Yes?
now the code below is for the above two questions
private void button1_Click(object sender, EventArgs e) { Task task = new Task(Processing); task.Start(); } private void Processing() { ParallelOptions parallelOptions = new ParallelOptions(); parallelOptions.MaxDegreeOfParallelism = 16; Stopwatch zTimer = new Stopwatch(); zTimer.Start(); using (ManualResetEvent mre = new ManualResetEvent(false)) { //Parallel.For(0, 10, parallelOptions , x => Parallel.For(0, 10, x => { Console.WriteLine("starting " + x); Thread.Sleep(x * 1000); Console.WriteLine("ending " + x); if (x == 9) mre.Set(); }); mre.WaitOne(); } zTimer.Stop(); Console.WriteLine("stop watch = " + zTimer.ElapsedMilliseconds); } }
Alle Antworten
-
Donnerstag, 8. März 2012 02:16Moderator
1) No. The threads used within the Parallel.For loop are not part of the UI, and you will need to synchronize to the UI appropriately. With the default TaskScheduler, the operations run in Parallel using the Parallel class will run on ThreadPool threads. The GUI thread gets blocked because it's waiting for the entire Parallel operation to complete.
2) Yes, and yes - but not because it's started from a Task, but rather because the Parallel.For section is that way anyways.
Also, your code is doing something odd with the ManualResetEvent - calling Set within a Parallel.For loop is likely not going to give the behavior you expect, as the loop runs in parallel, and there is no order guarantee that "x == 9" won't happen prior to "x == 3", for example....
Reed Copsey, Jr. - http://reedcopsey.com
If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".- Als Antwort markiert Scruffy John Donnerstag, 8. März 2012 21:27
-
Donnerstag, 8. März 2012 16:49
I follow your comment about ManualResetEvent (even though it does behave as expected, but probably just by luck).
interesting you said about Parallel threads not having access to the GUI thread. Your explaination matches a document I was reading from MS. But I have this code where Button4Run is called from Button4_Click event.. cannot move the window around while it is being executed, and the GUI does get updated as each parellel thread is finished (in Button4processStockList2).
public void Button4Run() { try { Parallel.For<StockItem>(0, listSI.Length, () => null, (j, loopStateVariable, returnValue) => { listSI[j].GetQuoteFromWebSite(); return listSI[j]; // this is coming back in the variable "returnValue" }, (x) => Button4processStockList2(x) // to do after thread has finished ); } catch (Exception e) { Console.WriteLine(e.Message); } } private void Button4processStockList2(StockItem SI) { // to do after each thread has finished UpdateGUI(SI); Console.WriteLine(SI.mTickerSymbol); } -
Donnerstag, 8. März 2012 17:12
another example where I would have thought I would not have access to the GUI thread to do GUI updates, but I do, and the GUI is not locked up even...
public void UseTaskFactorRun() { taskList = new Task[ParentClass.mTickerSymb.Length]; for (int i = 0; i < ParentClass.mTickerSymb.Length; i++) taskList[i] = taskFactory.StartNew(listSI_UseTaskFactor[i].GetQuoteFromWebSite); //allocate & start taskFactory.ContinueWhenAll(taskList, completedTasks => { //Do something foreach(StockItem SI in listSI_UseTaskFactor) UpdateGUI(SI); }); } -
Donnerstag, 8. März 2012 18:39Moderator
It's difficult to tell without seeing your methods (ie: UpdateGUI), but that is running on a ThreadPool thread, so updating the UI is not safe.
(The main exception is that the Parallel class will potentially use the current thread, as well as other threads, to perform its work - if there is only one item, it may not use a separate thread - but this is really not something to rely on...)
You can put a breakpoint in there, and look at the Threads window, in order to see this. You should see this break on different threads.
Reed Copsey, Jr. - http://reedcopsey.com
If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful". -
Donnerstag, 8. März 2012 18:52
hmm, I'm currently only using the Express version of VS/C#, so no thread window. I guess I was expecting an abend like I've seen the past that says a background thread or worker thread (a non-GUI thread) cannot access items on the GUI thread. The UpdateGUI function is simple enough:
private void UpdateGUI(StockItem SI) { dataGridView1.Rows[SI.GridRow].Cells[0].Value = SI.mTickerSymbol; dataGridView1.Rows[SI.GridRow].Cells[1].Value = SI.mCurrentQuote; dataGridView1.Rows[SI.GridRow].Cells[2].Value = SI.mChange.ToString("#0.00;(#0.00);Zero"); ; dataGridView1.Rows[SI.GridRow].Cells[2].Style = SI.mChange > 0 ? PositiveValue : NegativeValue; dataGridView1.Rows[SI.GridRow].Cells[3].Value = SI.mPctChange.ToString("#0.00%;(#0.00%);Zero"); dataGridView1.Rows[SI.GridRow].Cells[3].Style = SI.mChange > 0 ? PositiveValue : NegativeValue; } -
Donnerstag, 8. März 2012 19:05Moderator
You definitely shouldn't be doing this on a background thread. This should be using Control.Invoke or Control.BeginInvoke to marshal back to the UI thread.
Reed Copsey, Jr. - http://reedcopsey.com
If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful". -
Donnerstag, 8. März 2012 21:26ok, guess I can't trust getting abends when I thought I would.

