Form disappearing after thread closes.
Okay, this is probably a stupid question about threads, but I'm completely lost here...
So I made this network library that runs each client on a separate thread, and whenever a message arrives, starts a temporary thread that delivers the message as an event to the parent of the class. So far so good, messages get delivered the way they should.
Now I want to make a form visible as soon as a particular message is received. Now there is where it goes wrong. I created a ThreadSafeForm, with (for now) one method:
Code:
public class ThreadSafeForm : Form
{
delegate void SetBoolDelegate(bool parameter);
public void setVisible(bool value)
{
if (InvokeRequired)
{
this.BeginInvoke(new SetBoolDelegate(setVisible), value);
return;
}
this.Visible = value;
}
}
The problem is... When I call frmName.setVisible(true) after receiving the message, it indeed shows up for one millisecond, then disappears, assuming when the thread that delivered the message ends, that form is destroyed (or something similar)... Does anyone know why? I do invoke right? And I initialized the form at application start, so not in that message delivering thread...
Re: Form disappearing after thread closes.
Where is your form created? Have you handled the OnClosing (or something similar) event? Put a breakpoint and check the callstack to see what's closing it?
Re: Form disappearing after thread closes.
and me... I don't see any threads here so how can we help you if we see what's going on behind.
Re: Form disappearing after thread closes.
My psychic debugger fails when attempting to solve multithreaded issues. Set a conditional breakpoint on that line and examine the state of your program when Visible = false;
Re: Form disappearing after thread closes.
Okay to get things clear, I've created a small example. One project with two files: Program.cs and Form1.cs
The form has a button to create a thread which makes the other form visible... Or at least should...
Program.cs
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace ThreadProblem
{
static class Program
{
public static Form1 form1;
public static Form1 form2;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
form1 = new Form1();
form2 = new Form1();
Application.Run(form1);
}
}
}
Form1.cs
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace ThreadProblem
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
delegate void SetBoolDelegate(bool parameter);
public void setVisible(bool value)
{
if (InvokeRequired)
{
MessageBox.Show("invoke");
this.BeginInvoke(new SetBoolDelegate(setVisible), value);
return;
}
this.Visible = value;
}
private void button1_Click(object sender, EventArgs e)
{
Thread testThread = new Thread(showOtherForm);
testThread.Start();
}
public void showOtherForm()
{
Program.form2.setVisible(true);
}
}
}
Now if I press the button, why doesn't it show me messagebox with 'invoke' the first time, and why doesn't the second form show up (or only really fast)?
Re: Form disappearing after thread closes.
Have you used your debugger yet?
Re: Form disappearing after thread closes.
I think this.Visible = value should be in else branch:
Code:
public void setVisible(bool value)
{
if (InvokeRequired)
{
MessageBox.Show("invoke");
this.BeginInvoke(new SetBoolDelegate(setVisible), value);
return;
}
else
{
this.Visible = value;
}
}
Re: Form disappearing after thread closes.
BigEd781, yes, and what I found confirmed what I described in the first post. After the thread ends, the form disappears. I don't understand... It seems like some local instance is created or cloned or something. But why?
Re: Form disappearing after thread closes.
If the form is created and displayed in the thread, maybe if the thread ends, the message loop which drives the form is ended too and the form disappeare. But I'd to try it to be sure.
Re: Form disappearing after thread closes.
Okay I found something...
Code:
form2 = new Form1();
Does not actually create that form... I have to make it visible and then hide it to let everything be created in the UI thread. Modifying Program.cs in this way made the form stay... It looks stupid, and maybe there is a better way for it?
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace ThreadProblem
{
static class Program
{
public static Form1 form1;
public static Form1 form2;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
form1 = new Form1();
form2 = new Form1();
//briefly show the form to create it in this thread
form2.Visible = true;
form2.Visible = false; //and hide it again
Application.Run(form1);
}
}
}
Re: Form disappearing after thread closes.
Quote:
Originally Posted by
Kakoon
maybe there is a better way for it?
maybe... but to tell you that we need to know why you're doing this like that? I mean this show/hide thing.
Re: Form disappearing after thread closes.
Quote:
Originally Posted by
memeloo
maybe... but to tell you that we need to know why you're doing this like that? I mean this show/hide thing.
Well my previous post was a response to boudino's suggestion about the message loop ending when the thread ends. Hope this clears it up:
My assumption
Using the line
Code:
form2 = new Form1();
does not fully create the form and does not start the message loop boudino talked about. Making the form visible like I did with this trick...
Code:
form2.Visible = true;
form2.Visible = false;
... seemed to have caused the message loop to start in the UI thread (the thread that is running as long as the application is running), it will start that message loop. I can hide it again because I don't want the form to be visible just yet.
Result of this trick
Now when that temporary thread is created (which emulates an incoming network packet coming from another thread, i.e. a login success package and I want to hide the login form and show the main form), if I call SetVisible from that thread, then it actually invokes the object in the UI thread, because that form is still running in the background on the UI thread. So when this temporary (message delivering) thread ends, the form does not disappear.
What I'm looking for now
So I want somehow a way to let the message loop start (or whatever it is that is loaded upon Visible = true) without having to show the Form on forehand. Could look a bit messy when an application starts...
Re: Form disappearing after thread closes.
Quote:
Originally Posted by
Kakoon
Well my previous post was a response to boudino's suggestion about the message loop ending when the thread ends. Hope this clears it up:
you mean this?
Quote:
Originally Posted by
Kakoon
I have to make it visible and then hide it to let everything be created in the UI thread.
what for? to me it still does not make any sense.
Re: Form disappearing after thread closes.
Quote:
Originally Posted by
memeloo
what for? to me it still does not make any sense.
Hah, makes at much sense to you as it does to me, but it works and accidentally found it out by experimenting, and I want to find an explaination why it works... and how to make it work by using a less awkward way... If you try out the pieces of code before and after, you'll see what I mean...