How to create a form from inside non-gui thread c #

I have my main GUI, from where I run a long running method in a separate thread. Now from this separate stream I need to create and show a new form. But when I show this new form, all the controls get stuck and the window says โ€œnot respondingโ€.

What is the best way to solve this problem?

considers

Thomas

+4
source share
3 answers

Put the code that creates the new GUI into the main GUI class, and then call the main GUI invocation method or raise an event that the main GUI can sign up to find out when to launch the new GUI. If you choose the latter, be sure to use InvokeRequired to determine if you can invoke the method that creates the new GUI, or if you need to use Invoke to return to the GUI stream to create a new GUI.

+4
source

You need to learn about Control.BeginInvoke / Invoke and all this means. Just remember that all user interface operations must be performed in the main thread (user interface thread), because it is the thread that owns the message pump. You need to call back to this thread in order to have a UI action.

The text BeginInvoke / Invoke is entered here: http://weblogs.asp.net/justin_rogers/pages/126345.aspx

To further help here is a complete example of working code that should emphasize the basics.

public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { var worker = new Worker(this); worker.Start(); } public void updateLabel(int value) { if(label1.InvokeRequired) { // check if on UI thread //If true use begin invoke to call update on UI thread //this calls the anonymous delegate in the UI thread //that then calls the updateLabel function again to set the label text label1.BeginInvoke(new MethodInvoker(() => this.updateLabel(value))); return; } label1.Text = value.ToString(); } public void showNewForm() { if(this.InvokeRequired) { // check if on UI thread this.BeginInvoke(new MethodInvoker(this.showNewForm)); // we need to create the new form on the UI thread return; } var anotherForm = new Form1(); anotherForm.Show(); } } class Worker { private volatile bool stop = false; private Form1 form; public Worker(Form1 form) { this.form = form; } public bool Stop { get { return stop; } set { stop = value; } } public void Start() { var thread = new Thread(this.work); thread.IsBackground = true; thread.Start(); } private void work() { int i = 0; while(!stop) { i++; Thread.Sleep(100); form.updateLabel(i); if(i == 50) { form.showNewForm(); // call into form // can also do the invokerequired check here and create new form w/ anonymous functions // however, I'd recommend keeping all the UI code in the same place. } } } } 
+2
source

Use Form.Show instead of Form.ShowDialog. You can also use BackgroundWorker to do parallel tasks.

0
source

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


All Articles