The point is that the body of the function that you pass to Parallel.ForEach()
is executed in other threads. Inside this function, you access the UI component. But UI-components allow you to work with yourself only in the same thread in which they were created. Using the IsInvokeRequired
check and the Invoke()
call, you "redirect" the call to the component to the main (UI) thread and thus solve the problem.
In addition, as indicated in the comments, you have in the code "oil oil". The point is that the Task.Factory.StartNew()
call performs the function passed to it in a separate thread. However, this call is already happening in a separate thread , since you are using Parallel.ForEach()
. To this is added the problem of handling exceptions: the delegate that you pass to Parallel.ForEach()
is async void
and is dangerous because you either don’t know about the exception, or you learn, but it’s too late - the process will fail.
You must either remove the call to Task.Factory.StartNew()
(you do not need the external variable, either):
Parallel.ForEach(richTextBox1.Lines, item => { var oa = Wor.SomeLongOperation(item) + "\n"; // вызов richTextBox2.AppendText(oa) через Invoke });
Either remove Parallel.ForEach()
(this option will work slower, because we perform a long operation in another stream one after another, and not immediately with a bundle, as is the case with Parallel.ForEach()
):
foreach (var item in richTextBox1.Lines) { var oa = await Task.Factory.StartNew( () => Wor.SomeLongOperation(item), TaskCreationOptions.LongRunning) +"\n"; richTextBox2.AppendText(oa); };
Also, for such a code, it is usually accepted to divide the step “do something in a separate thread” and step “output the result to the UI”. For example, if you use async / await, the class Progress<T>
comes to the rescue.
Parallel.ForEach
and asynchronous methods are not friendly. - Pavel Mayorov