I use Parallel.ForEach as a multithreading, there was a problem in adding a pause and continuing work.

var lines = File.ReadAllLines(@dann[0]); int kol = Convert.ToInt32(dann[1]); var pr = File.ReadAllLines(@dann[2]); var opt = new ParallelOptions { MaxDegreeOfParallelism = kol }; Parallel.ForEach(lines, opt, a => start(a, pr)); 

How can I pause and then continue?

  • one
    Where exactly do you need a pause and why? - isnullxbh
  • I need to suspend multithreading, tobish in the start procedure, I send a string and an array. Suppose most of the lines array passed (for example, only 10 lines) I pause (through a certain boolean variable) and no values ​​are transferred to the start procedure (stopped at 6th flow), after continuing work (changed back to the boolean variable, for example) again procedure call from a previously stopped location (from 6 lines) - Lolidze
  • I'm sorry, I don't express my thoughts well, I hope you understand, if not, I will try to paraphrase - Lolidze
  • No, all is fine. You need to use lambda. Take a look at this example. - isnullxbh
  • If you do not manage, place your code somewhere in the cloud, I will help. - isnullxbh

3 answers 3

Try the following approach.

Add a field to your code

 ManualResetEventSlim mres = new ManualResetEventSlim(true); 

In the start method add a call

 mres.Wait(); 

In the place where you need to enable / disable a pause (for example, in the button press handler) write

 if (mres.IsSet) mres.Reset(); else mres.Set(); 

Using the class ManualResetEventSlim guarantees thread safety.

  • thanks a lot, it seems to work - Lolidze
  • and how can you stop multithreading? - Lolidze
  • @Lolidze - one topic - one question. Moreover, do not ask questions in the comments, ask a new separate question. And so, see canceling tasks using CancellationToken and stopping the loop using ParallelLoopState . - Alexander Petrov

Look, if you use such a code, it should work. However, there is one stream, and the whole point of using Parallel.ForEach is lost (MaxDegreeOfParallelism = 1). Otherwise, the blocking will work for the new stream that Parallel.ForEach creates and for the stream in which it works, and this is not exactly what is needed.

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace parallelOutput { class Program { public static void MainTask(ManualResetEvent re) { string[] recs = { "str_01", "str_02", "pause", "str_03" }; ParallelLoopResult plr = Parallel.ForEach(recs, new ParallelOptions() { MaxDegreeOfParallelism = recs.Count() }, (string rec, ParallelLoopState pls) => { if (rec != "pause") { Console.WriteLine("{0} : {1} ", DateTime.Now, rec); } else { re.WaitOne(); } }); } public static void StartTask(ManualResetEvent re) { Thread.Sleep(10000); re.Set(); } static void Main(string[] args) { ManualResetEvent re = new ManualResetEvent(false); Thread st = new Thread(() => StartTask(re)); st.Start(); Thread mt = new Thread(() => MainTask(re)); mt.Start(); } } } 
  • thanks a lot for the help - Lolidze
  • @Lolidze, there’s nothing, especially since I haven’t solved your problem. As I understand it, it is impossible to use such a technique specifically for the Parallel.ForEach construction. Although, if someone proves the opposite - I will only be glad) - isnullxbh
  • and the example above? he seems to be working fine - Lolidze
  • @Lolidze, now ask VladD) - isnullxbh

The easiest, probably, is to stop / start the code like this:

Declare a public object:

 object mutex = new object(); 

In the place that should be stopped (for example, at each iteration of the cycle):

 lock (mutex) { /* ничего не делать, сразу освободить */ } 

In the place where it is necessary to prohibit the execution:

 lock (mutex) { // тут выполнение потоков остановлено Thread.Sleep(1000); } // а тут снова разрешено 

Well, or if it is necessary to prohibit execution in one place and allow it in another, then

 Monitor.Enter(mutex); // запретить // ... Monitor.Exit(mutex); // разрешить 

But if you need to start / stop the execution of code, Parallel.ForEach probably not the best idea: after all, the internal scheduler in it assumes that it needs to execute everything as quickly as possible, and does not know that your code will stop.

  • Tell me please, is it possible to use your method in the case when we need some kind of event in order to stop / resume work? I hope you do not consider my question an attempt to prove the advantage of my method on yours - somehow participants became aggravated relate to the comments on their answers)) - isnullxbh
  • @isnullxbh: Well, in theory, you can. For example, to stop through Monitor.Enter , and on arrival of an event to make Monitor.Exit . - VladD
  • Understood thanks ! - isnullxbh Nov.
  • @isnullxbh: Please! - VladD
  • one
    @Lolidze: He also has a good method. - VladD