2

Recently I was able to convert a for loop into a Parallel.For loop to speed up an heavy task in my WinForms application initialization.

I was quite surprised though, to see some OnPaint() calls coming through when the Parallel.For() is in action.

Why does this happen? Is there any way to prevent the UI from working during a Parallel.For?

EDIT: I want to save time but not change the program logic: I want the Parallel.For to work exactly as the for and save time. UI depends on the result of the for loop and the OnPaint() fails because the data is not ready yet.

abenci
  • 8,422
  • 19
  • 69
  • 134
  • *Prevent UI from working* is easy. Prevent repaints during long operation is not. Some controls have `BeginUpdate`/`EndUpdate`, `SuspendLayout`/`EndLayout` so that you can start doing something with many items/controls without causing `OnPaint` event after each modification. Best would be if you post a part of code, maybe you doing something wrong/not optimal there. You can disable repaint by making control invisible, doing modification via buffer (with copy), etc. – Sinatr Feb 07 '14 at 13:19
  • "I want to save time but not change the program logic" You can't just change a set of synchronous calls to a set of asynchronous calls and expect everything to work, *because you are fundamentally changing how your application executes*. If you don't understand this, I would suggest you learn about threading before you try to make everything multithreaded without realising the potential consequences. – Ian Kemp Feb 07 '14 at 15:06
  • @Ian: you could be right but I am really surprised by this. How could I achieve what I am asking? Maybe the `Parallel.For` is not the best choice... – abenci Feb 07 '14 at 16:00
  • 1
    @Alberto you need to rewrite the whole thing to be honest. If you have some time consuming thing you should not just replace it with `Parallel.For` because it is blocking call, you need to move it out to `Task` or something similar. Your UI should not depend on data to be there, your task should notify UI on completion. – Andrey Feb 07 '14 at 18:11

2 Answers2

2

You should never block UI thread (prevent the UI from working). It makes the application unresponsive which users don't like. You should handle it gracefully by graying out form and showing progress bar.

Andrey
  • 59,039
  • 12
  • 119
  • 163
  • 2
    The question was not about blocking the thread which updates the UI but how to prevent UI from updating. – Trifon Feb 07 '14 at 13:10
  • @Trifon question was stated as how to "prevent the UI from working". This is not very specific, but my argument is that you should block UI from working using user-friendly techniques and not by neither blocking UI thread or suspending layout, – Andrey Feb 07 '14 at 13:16
0

Try calling this.SuspendLayout() on the form that represents the UI. After computations are finished allow again updating of the UI with this.ResumeLayout()

Edit: Also you should not run code which updates controls from a thread different from the one which has created them. If doing so, it has to be done through the Invoke methods.

Trifon
  • 1,081
  • 9
  • 19
  • It is not "should not" it is you can not. It will throw exception. – Andrey Feb 07 '14 at 13:11
  • You "should not" because it will throw an exception. But you can always write code that throws exceptions! :-) – Trifon Feb 07 '14 at 13:13
  • Also check this http://stackoverflow.com/questions/835100/winforms-suspendlayout-resumelayout-is-not-enough – Andrey Feb 07 '14 at 13:17
  • yeah sure, you can even catch this exception. But your code will do nothing in this case. There is absolutely no way to do this from non UI thread. (except possibly something very hackish). – Andrey Feb 07 '14 at 13:18
  • @Andrey This "very hachish" thing is very well documented though: http://msdn.microsoft.com/en-us/library/757y83z4.aspx – Trifon Feb 07 '14 at 13:21
  • I recommend you to do minimal research before you start teaching others. Invoke is not the way to manipulate controls from other threads, it is mechanism that sends message to the owner thread (UI). Control is still mutated at his owner thread. I meant that by doing Invoke you still do not modify it in the thread you call it. http://stackoverflow.com/questions/770497/how-does-invoke-work-underneath-doesnt-thread-have-only-1-instruction-pointer – Andrey Feb 07 '14 at 13:26
  • It is a mehod for altering a property of a control that has been created by thread A (UI thread), while running code from thread B. The actual uptade yes it is done by thread A, but the Invoke is done by thread B and thread B tells how to alter the property of the control. The last thing I would like to do is to teach someone who knows everything. – Trifon Feb 07 '14 at 13:33
  • I really don't get your point, nothing you presented so far contradicts with what I said initially. – Andrey Feb 07 '14 at 14:14