I have a task - to create a label from textboxes, width TableWidth , height TableHeigth . For large values ​​(50 * 50), the plate is created for quite a long time, so I decided to do a parallel drawing along the lines. But the given code completely weighs the program. Please tell me what could be wrong? There are suggestions that a thread-safe operation is performed somewhere, but where exactly ...

 Parallel.For(1, table.TableWidth + 1, x => { var i = x; for (int y = 1; y <= table.TableHeight; y++) { var j = y; TextBox textbox; if (!textBoxes.ContainsKey(new Point(i, j))) { textbox = new TextBox(); textBoxes.Add(new Point(i, j), textbox); textbox.BorderStyle = BorderStyle.Fixed3D; Controls.Add(textbox); } textbox = textBoxes[new Point(i, j)]; textbox.Location = new Point(ColumnsCoords[i], RowsCoords[j]); textbox.Width = table.ColumnsWidth[i]; textbox.Height = table.RowsHeight[j]; textbox.Text = table[i, j].Data; textbox.GotFocus += (s, a) => { focusedCellCoords.Text = new Point(i, j).ToString(); currentTextBox = textbox; focusedCell.Text = textbox.Text; }; textbox.TextChanged += (s, a) => { PushData(new Point(i, j), textbox.Text); currentTextBox = textbox; focusedCell.Text = textbox.Text; }; } }); 
  • 2
    If my memory serves me correctly, the whole UI should be in one thread and spreading it to different threads requires not only a tambourine, but also an experienced shaman. Well, the traditional question - WPF or WinForms? - rdorn
  • In this case, using WinForms - Stepan
  • And what does "long" mean? And I don’t see serious calculations in your code, so I strongly doubt that splitting into threads will help. And yes, all controls should be created in a UI thread, so only long calculations can be brought into the background thread. - VladD
  • one
    Too many questions about your code. What is a table ? textBoxes collection thread safe? Is it planned to further remove these textboxes? Events in the form of lambda will not allow to unsubscribe from them - a memory leak is possible. - Alexander Petrov
  • And in general, isn't it easier to take a component of the DataGridView type? Or, for example, TableLayoutPanel for textboxes? - Alexander Petrov

2 answers 2

Even if the code you cited did not hang the program, it would not work. The fact is that any control listens to events in the stream in which it was created. But the message loop runs only in the main thread of the application, the pool threads cannot receive window messages. Therefore, your textboxes will not react to events (you cannot even enter text in them, entering text also requires an active message processing loop).

The only possible solution is to throw out Parallel.For and replace it with a regular for loop.


As for the "hanging" of the program, I would venture to suggest that a deadlock occurs in the Controls.Add(textbox); line Controls.Add(textbox); - surely this method needs to send a window message to the main UI thread, and it is just busy with the for loop. But this is fortune telling, if accuracy is needed - run the debugger and check where it hangs exactly.

Another possible error of yours - judging by the code, textBoxes is a regular dictionary ( Dictionary<Point,TextBox> ). But you cannot work with a dictionary from several streams at the same time! If the code had any meaning at all, you should use ConcurrentDictionary<,> for the same purpose.

    It makes sense to implement in the form of a normal cycle, as written above, but wrap it in async / await. Then a long cycle will not hang the GUI.

    You can see here https://stephenhaunts.com/2014/10/14/using-async-and-await-to-update-the-ui-thread/

    • Will not help. In the loop, controls are created (it cannot be pulled out into another thread) and there are no long operations. - Pavel Mayorov