Execution of two forms in the form of different threads (or at least 2 forms executed "in parallel")

I want to do the following (C #)

  • I have a form, call Form1
  • Form1 creates Form2
  • The Form2 constructor (GUI, variables ..) is executed. Latest Form2 instructions: create and show Form3
  • Form 2 contains Label1
  • Form2 creates Form3 and passes a link to Form3
  • Form3 edit the shortcut1 (form2) many times (say 100)

This is normal ... everything works, but .. The problem is that Form3 takes a long time to start all operations (let it be 10 seconds). At the end (at the same time), two forms Form2 and Form3 are displayed, but I want Form2 to be visible BEFORE FORM3 because I want that although Form3 operations are performed (including editing label1 in Form2), Form2 shows each Label1 update (for example, "Execution: operation 1", then "Execution: operation 2", etc.).

I also tried to make the button (Button1) in Form2 by specifying the Button1_onClick () event and executing its contents using "create and show Form3". But when I press Button1, Form2 “disappears” (for example, when a Windows application is locked and it becomes “paused”), and it only shows the last label (“Operation: 100”) at the very moment that Form3 appears.

Summary of my question: -> I have 3 forms

  • Form1
  • Form 2 (labeled 1)
  • Form3 (editing label 1 on form2)

-> What should happen:

  • Form1 creates and displays Form2
  • Form2 creates and shows Form3
  • Form3 performs various operations (for example, creating a list, ordering it ...), and for each operation Label1 is updated (and the user MUST see the update process) in Form2

All Form2 operations are called from a function called in the Form2 constructor, like: Form2_Constructor () => call makeOperations () -> makeOperations () => call Operation1 (), then Operation2 (), and finally Operation3 (), where each operationX () contains a loop (say, out of 30 iterations) that performs some operation and calls Form2.setLabel1 ("Operation Name");

My idea (as the name says) is to make two different threads. .. or at least find a way to have two forms running in "parallel mode" (this way Form2 does not work when Form3 performs operations).

Any idea how to solve this problem?

+4
source share
3 answers

If you really need two different forms that work in separate threads, you will need to create another thread that starts the message loop through Application.Run . However, this approach is not recommended. This can cause strange problems, and it is difficult to access the two to each other to each other, because all calls from one to the other requires marshaling using Control.Invoke .

I advise sticking to a single user interface thread. Get as much long code as currently running Form3 into the workflow. As your workflow progresses, you can slowly publish results to Form3 . Publishing results to Form3 can be done in one of two ways.

  • Ask the workflow to click on Form3 by invoking Invoke or BeginInvoke
  • Conduct a Form3 survey of the overall data structure for the results published by the workflow.

Those who keep track of my answers already know which one I recommend: a later method in which polling the user interface checks the results. It has the following advantages.

  • It breaks the tight connection between the user interface and the workflows that Control.Invoke imposes.
  • He is responsible for updating the user interface in the user interface thread, where he must belong in any case.
  • The user interface flow determines when and how often an update should occur.
  • There is no risk of user interface message overflow, as would be the case with marshaling methods initiated by a workflow.
  • The workflow should not wait for confirmation that the update has been completed before proceeding with the next steps (i.e. you will get more bandwidth for both the user interface and workflows).

If the work currently being Form3 cannot be easily moved to the workflow (perhaps it controls the user interface controls most of the time, which can only be done from the user interface thread hosting the form), then you will need to slow down. when this work is done to give more time for the form to respond to user input. This means that you will be forced to make some sacrifices. For example, instead of filling the grid with thousands of lines, you may need to fill it with only hundreds at a time and provide some kind of paging behavior that will allow the user to move on to the next hundred.

+3
source

In general, you should keep your entire user interface in the main thread and perform lengthy tasks in the background.

Depending on the version of .Net you are using and what this background work is, you can use the BackgroundWorker, ThreadPool, or .Net 4.0 Task classes.

No matter which one you use, when you update the status in the user interface, you have to use the Invoke method to update it, otherwise you will get an exception due to an attempt to update the control from the stream, it was not created.

There are a number of articles written on background threads and updating the user interface .

Here is an article about . Net task 4 and a WinForms (full disclosure, it's my article).

Here's a basic VS project that mimics what you described - three forms that start each other, with a 3rd form performing background operation and updating status to form 2 (with background work being performed by the BackgroundWorker control).

0
source

Yes. Sit down and program. Start another thread, create another form in it and start the dispatcher. Then use standard messaging semantics for negotiation between forms.

-4
source

Source: https://habr.com/ru/post/1397991/


All Articles