Creating forms on different threads
-
This is my situation. I am creating an instant messenger I have a main method which calls application.run(new form1()) This launches my main form. I start another thread in my form1 constructor that sits in the background and soley listens for incoming connections code: public form1() { InitializeComponent() Thread t = new Thread(new ThreadStart(ListenNewConnections)); t.Start(); } When thread t finally gets a new connection that thread itself shoots off another thread "A" to handle that particular connection thru out its life span. Once that connection is done so is the thread. Now when thread "A" is handling a specific connection I want it to create a form - this is where the problem starts. 1st thing i did newform.Show() - creates a blank form and when mouse over u get hour glass I think the reason for this is because it is not starting on the main thread for message pumping. Ok so second thing i do is use a delegate this.BeginInvoke(new createFormdelegate(createForm)); //create form method simply initializes a new form and calls newform.Show(). but when i debug it stops at the this.BeginInvoke line an gives me this error "Invoke or BeginInvoke cannot be called on a control until the window handle has been created." I know i am doing something wrong. Maybe my c# logical thinking is off i dont know. Please help Thanks in advance Kourvoisier
-
This is my situation. I am creating an instant messenger I have a main method which calls application.run(new form1()) This launches my main form. I start another thread in my form1 constructor that sits in the background and soley listens for incoming connections code: public form1() { InitializeComponent() Thread t = new Thread(new ThreadStart(ListenNewConnections)); t.Start(); } When thread t finally gets a new connection that thread itself shoots off another thread "A" to handle that particular connection thru out its life span. Once that connection is done so is the thread. Now when thread "A" is handling a specific connection I want it to create a form - this is where the problem starts. 1st thing i did newform.Show() - creates a blank form and when mouse over u get hour glass I think the reason for this is because it is not starting on the main thread for message pumping. Ok so second thing i do is use a delegate this.BeginInvoke(new createFormdelegate(createForm)); //create form method simply initializes a new form and calls newform.Show(). but when i debug it stops at the this.BeginInvoke line an gives me this error "Invoke or BeginInvoke cannot be called on a control until the window handle has been created." I know i am doing something wrong. Maybe my c# logical thinking is off i dont know. Please help Thanks in advance Kourvoisier
This being your worker thread: private static void ShowMyForm() { frmMyForm frmg = new frmMyForm(); Application.Run(frm); } If you want to make any calls that are thread dependant (on the window handle), like calling from one thread to another to set the focus of a control, that is when you use BeginInvoke. As the error points out, you can only call BeginInvoke when all handles are created. Jon Humphreys ActivePlanet Software Bangkok, Thailand
-
This being your worker thread: private static void ShowMyForm() { frmMyForm frmg = new frmMyForm(); Application.Run(frm); } If you want to make any calls that are thread dependant (on the window handle), like calling from one thread to another to set the focus of a control, that is when you use BeginInvoke. As the error points out, you can only call BeginInvoke when all handles are created. Jon Humphreys ActivePlanet Software Bangkok, Thailand
I dont understand? 1> what is the window handle? how do i know it is created? how do i create a handle?
jonny5 wrote:
private static void ShowMyForm() { frmMyForm frmg = new frmMyForm(); Application.Run(frm); }
Are you telling me to call Application.Run(newForm) everytime i create a new form. Keep in mine everytime a new connection comes in a new thread and form is created to handle that connection and communication between the two endpoints. I thought Application.Run() was to be only called once???
jonny5 wrote:
If you want to make any calls that are thread dependant (on the window handle), like calling from one thread to another to set the focus of a control, that is when you use BeginInvoke. As the error points out, you can only call BeginInvoke when all handles are created.
I thought that is what i was doing in the code i showed...maybe not could you explain because i was trying to create and set focus the new form with the BeginInvoke. please help still confused. Thanks alot! Kourvoisier
-
I dont understand? 1> what is the window handle? how do i know it is created? how do i create a handle?
jonny5 wrote:
private static void ShowMyForm() { frmMyForm frmg = new frmMyForm(); Application.Run(frm); }
Are you telling me to call Application.Run(newForm) everytime i create a new form. Keep in mine everytime a new connection comes in a new thread and form is created to handle that connection and communication between the two endpoints. I thought Application.Run() was to be only called once???
jonny5 wrote:
If you want to make any calls that are thread dependant (on the window handle), like calling from one thread to another to set the focus of a control, that is when you use BeginInvoke. As the error points out, you can only call BeginInvoke when all handles are created.
I thought that is what i was doing in the code i showed...maybe not could you explain because i was trying to create and set focus the new form with the BeginInvoke. please help still confused. Thanks alot! Kourvoisier
anyone out there? know about this stuff
-
anyone out there? know about this stuff
Hi there. I hope that this code helps. It starts a thread in the main form's constructor and, then, when a new connection gets accepted, opens a new child form.
using System;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;namespace FormsSpawnedByThreads
{
public class MainForm : Form
{
public MainForm() : base()
{
Text = "Spawn Some Forms";
Height = 150;
Width = 300;
Button b = new Button();
b.Text = "Connect";
b.Top = ( Height - b.Height ) / 2 - ( b.Height / 2 );
b.Left = ( Width- b.Width ) / 2;
b.Click += new EventHandler( b_Click );
Controls.Add( b );
Thread t = new Thread( new ThreadStart( ListenNewConnections ) );
t.IsBackground = true;
t.Name = "Main Listener";
t.Start();
clients = new TcpClient[ 5 ];
Closing += new System.ComponentModel.CancelEventHandler( MainForm_Closing );
}private void ListenNewConnections() { IPEndPoint endPoint = new IPEndPoint( 0x7F000001, 5050 ); listener = new TcpListener( 5050 ); listener.Start(); while( true ) { listener.AcceptTcpClient(); ChildForm cf = new ChildForm(); cf.Show(); } } private void b\_Click( object sender, EventArgs e ) { clients\[ clientIndex++ \] = new TcpClient( "localhost", 5050 ); if( clientIndex == 5 ) { Controls\[ 0 \].Enabled = false; } } private void MainForm\_Closing(object sender, System.ComponentModel.CancelEventArgs e) { if( listener != null ) { listener.Stop(); } } private TcpClient\[\] clients; private int clientIndex; private TcpListener listener; \[STAThread\] public static void Main() { Application.Run( new MainForm() ); } } public class ChildForm : Form { public ChildForm() : base() { } }
}
"we must lose precision to make significant
statements about complex systems."
-deKorvin on uncertainty -
anyone out there? know about this stuff
I reread your post and you wanted to spawn threads for the connections, as well. Try the following code to do that, too. I hope that helps.
using System;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;namespace FormsSpawnedByThreads
{
public class MainForm : Form
{
public MainForm() : base()
{
Text = "Spawn Some Forms";
Height = 150;
Width = 300;
Button b = new Button();
b.Text = "Connect";
b.Top = ( Height - b.Height ) / 2 - ( b.Height / 2 );
b.Left = ( Width- b.Width ) / 2;
b.Click += new EventHandler( b_Click );
Controls.Add( b );
Thread t = new Thread( new ThreadStart( ListenNewConnections ) );
t.IsBackground = true;
t.Name = "Main Listener";
t.Start();
clients = new TcpClient[ 5 ];
Closing += new System.ComponentModel.CancelEventHandler( MainForm_Closing );
}private void ListenNewConnections() { IPEndPoint endPoint = new IPEndPoint( IPAddress.Parse( "127.0.0.1" ), 5555 ); listener = new TcpListener( endPoint ); listener.Start(); while( true ) { try { TcpClient client = listener.AcceptTcpClient(); this.Invoke( new HandleNewConnection( OpenChildForm ), new object\[\] { client } ); } catch( SocketException ) {} } } private delegate void HandleNewConnection( TcpClient client ); private void OpenChildForm( TcpClient client ) { ChildForm cf = new ChildForm( client ); cf.Show(); } private void b\_Click( object sender, EventArgs e ) { clients\[ clientIndex++ \] = new TcpClient( "127.0.0.1", 5555 ); if( clientIndex == 5 ) { Controls\[ 0 \].Enabled = false; } } private void MainForm\_Closing(object sender, System.ComponentModel.CancelEventArgs e) { if( listener != null ) { listener.Stop(); } } private TcpClient\[\] clients; private int clientIndex; private TcpListener listener; \[STAThread\] public static void Main() { Application.Run( new MainForm() ); } } public class ChildForm : Form { public ChildForm( TcpClient client ) : base() { c = client; Closing += new System.ComponentModel.CancelEventHandler( ChildForm\_Closing ); // Start thread here to handle client's stuff. } private void ChildForm\_Closing(object sender, System.ComponentModel.CancelEventArgs e) { c.Close(); } private TcpClient c; }
}
-
I reread your post and you wanted to spawn threads for the connections, as well. Try the following code to do that, too. I hope that helps.
using System;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;namespace FormsSpawnedByThreads
{
public class MainForm : Form
{
public MainForm() : base()
{
Text = "Spawn Some Forms";
Height = 150;
Width = 300;
Button b = new Button();
b.Text = "Connect";
b.Top = ( Height - b.Height ) / 2 - ( b.Height / 2 );
b.Left = ( Width- b.Width ) / 2;
b.Click += new EventHandler( b_Click );
Controls.Add( b );
Thread t = new Thread( new ThreadStart( ListenNewConnections ) );
t.IsBackground = true;
t.Name = "Main Listener";
t.Start();
clients = new TcpClient[ 5 ];
Closing += new System.ComponentModel.CancelEventHandler( MainForm_Closing );
}private void ListenNewConnections() { IPEndPoint endPoint = new IPEndPoint( IPAddress.Parse( "127.0.0.1" ), 5555 ); listener = new TcpListener( endPoint ); listener.Start(); while( true ) { try { TcpClient client = listener.AcceptTcpClient(); this.Invoke( new HandleNewConnection( OpenChildForm ), new object\[\] { client } ); } catch( SocketException ) {} } } private delegate void HandleNewConnection( TcpClient client ); private void OpenChildForm( TcpClient client ) { ChildForm cf = new ChildForm( client ); cf.Show(); } private void b\_Click( object sender, EventArgs e ) { clients\[ clientIndex++ \] = new TcpClient( "127.0.0.1", 5555 ); if( clientIndex == 5 ) { Controls\[ 0 \].Enabled = false; } } private void MainForm\_Closing(object sender, System.ComponentModel.CancelEventArgs e) { if( listener != null ) { listener.Stop(); } } private TcpClient\[\] clients; private int clientIndex; private TcpListener listener; \[STAThread\] public static void Main() { Application.Run( new MainForm() ); } } public class ChildForm : Form { public ChildForm( TcpClient client ) : base() { c = client; Closing += new System.ComponentModel.CancelEventHandler( ChildForm\_Closing ); // Start thread here to handle client's stuff. } private void ChildForm\_Closing(object sender, System.ComponentModel.CancelEventArgs e) { c.Close(); } private TcpClient c; }
}
Thanks for responding tho i have already come up with a solution very similar to the one you have. The major difference is that i use sockets instead of tcplisteners(i have learned you can do much more with that class). I do run into a major problem tho. Main form created good and i create a new thread specifically to listen for incoming connections works great. New connection comes in and i spawn off a new thread for it and create a form perfect. but when i try to add or write data to that form's text box using form.textbox.text """"I GET THIS ERROR AGAIN"""" "Invoke or BeginInvoke cannot be called on a control until the window handle has been created." I use the beginInvoke(new delegate(method), {object [], String s}) to call a method that changes the textbox to display the message that has been received on the specific connection thread. I am able to add data to the text box on the main form but not the connection specific form created on the connection specific thread. Thanks hopes this all makes since Kourvoisier
-
Thanks for responding tho i have already come up with a solution very similar to the one you have. The major difference is that i use sockets instead of tcplisteners(i have learned you can do much more with that class). I do run into a major problem tho. Main form created good and i create a new thread specifically to listen for incoming connections works great. New connection comes in and i spawn off a new thread for it and create a form perfect. but when i try to add or write data to that form's text box using form.textbox.text """"I GET THIS ERROR AGAIN"""" "Invoke or BeginInvoke cannot be called on a control until the window handle has been created." I use the beginInvoke(new delegate(method), {object [], String s}) to call a method that changes the textbox to display the message that has been received on the specific connection thread. I am able to add data to the text box on the main form but not the connection specific form created on the connection specific thread. Thanks hopes this all makes since Kourvoisier
I agree with you: the Socket class has much more functionality. If you can bear with me, though, I modified my last example with the TcpLiseners to handle actual messages passed into the child forms.
using System;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;namespace FormsSpawnedByThreads
{
public class MainForm : Form
{
public MainForm() : base()
{
Text = "Spawn Some Forms";
Height = 150;
Width = 300;
Button b = new Button();
b.Text = "Connect";
b.Top = ( Height - b.Height ) / 2 - ( b.Height / 2 );
b.Left = ( Width- b.Width ) / 2;
b.Click += new EventHandler( b_Click );
Controls.Add( b );
Thread t = new Thread( new ThreadStart( ListenNewConnections ) );
t.IsBackground = true;
t.Name = "Main Listener";
t.Start();
clients = new TcpClient[ 5 ];
Closing += new System.ComponentModel.CancelEventHandler( MainForm_Closing );
}private void ListenNewConnections() { IPEndPoint endPoint = new IPEndPoint( IPAddress.Parse( "127.0.0.1" ), 5555 ); listener = new TcpListener( endPoint ); listener.Start(); while( true ) { try { TcpClient client = listener.AcceptTcpClient(); this.Invoke( new HandleNewConnection( OpenChildForm ), new object\[\] { client } ); } catch( Exception ) {} } } private delegate void HandleNewConnection( TcpClient client ); private void OpenChildForm( TcpClient client ) { ChildForm cf = new ChildForm( client ); cf.Show(); } private void b\_Click( object sender, EventArgs e ) { clients\[ clientIndex \] = new TcpClient( "127.0.0.1", 5555 ); byte\[\] b = System.Text.Encoding.ASCII.GetBytes( message ); clients\[ clientIndex \].GetStream().Write( b, 0, b.Length ); clientIndex++; if( clientIndex == 5 ) { Controls\[ 0 \].Enabled = false; } } private void MainForm\_Closing(object sender, System.ComponentModel.CancelEventArgs e) { if( listener != null ) { listener.Stop(); } } private TcpClient\[\] clients; private int clientIndex; private TcpListener listener; \[STAThread\] public static void Main() { Application.Run( new MainForm() ); } private string message = "It was many and many a year ago in a kingdom by the sea\\n" + "Where a maiden there lived whom you may know by the name of Annabel Lee.\\n" + "And, this
-
I agree with you: the Socket class has much more functionality. If you can bear with me, though, I modified my last example with the TcpLiseners to handle actual messages passed into the child forms.
using System;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;namespace FormsSpawnedByThreads
{
public class MainForm : Form
{
public MainForm() : base()
{
Text = "Spawn Some Forms";
Height = 150;
Width = 300;
Button b = new Button();
b.Text = "Connect";
b.Top = ( Height - b.Height ) / 2 - ( b.Height / 2 );
b.Left = ( Width- b.Width ) / 2;
b.Click += new EventHandler( b_Click );
Controls.Add( b );
Thread t = new Thread( new ThreadStart( ListenNewConnections ) );
t.IsBackground = true;
t.Name = "Main Listener";
t.Start();
clients = new TcpClient[ 5 ];
Closing += new System.ComponentModel.CancelEventHandler( MainForm_Closing );
}private void ListenNewConnections() { IPEndPoint endPoint = new IPEndPoint( IPAddress.Parse( "127.0.0.1" ), 5555 ); listener = new TcpListener( endPoint ); listener.Start(); while( true ) { try { TcpClient client = listener.AcceptTcpClient(); this.Invoke( new HandleNewConnection( OpenChildForm ), new object\[\] { client } ); } catch( Exception ) {} } } private delegate void HandleNewConnection( TcpClient client ); private void OpenChildForm( TcpClient client ) { ChildForm cf = new ChildForm( client ); cf.Show(); } private void b\_Click( object sender, EventArgs e ) { clients\[ clientIndex \] = new TcpClient( "127.0.0.1", 5555 ); byte\[\] b = System.Text.Encoding.ASCII.GetBytes( message ); clients\[ clientIndex \].GetStream().Write( b, 0, b.Length ); clientIndex++; if( clientIndex == 5 ) { Controls\[ 0 \].Enabled = false; } } private void MainForm\_Closing(object sender, System.ComponentModel.CancelEventArgs e) { if( listener != null ) { listener.Stop(); } } private TcpClient\[\] clients; private int clientIndex; private TcpListener listener; \[STAThread\] public static void Main() { Application.Run( new MainForm() ); } private string message = "It was many and many a year ago in a kingdom by the sea\\n" + "Where a maiden there lived whom you may know by the name of Annabel Lee.\\n" + "And, this
Just curious if this happens to you... my machine seems to drastically drag when i start running the 2nd thread Both threads are continously running in the loop while(true) { if Connection is Pending then Accept Socket } one is listening for new connections and the other listening with a direct connection Is this best practice for listening on sockets..... (running loops like this) How do yahoo instant messengers handle listening on sockets? what about AOL messengers? Is there another way of handling this w/o loops? do they all have loops running like this.... just curious Kourvoisier -- modified at 18:19 Monday 14th November, 2005