Is this Application.Run() correct?

J

Jon Skeet [C# MVP]

j m said:
I changed my Form to not use the Threadpool at all and instead use
Application.Run(new Form1()); (please see earlier in the thread).

I then started the thread in the Form_Load.

The problem, for me anyway, is that I am calling that Form1 that started
the thread from the clsListen.

Here is what I don't understand, then: If I can start a thread like
this and pass it my form via "this," keyword, constructor in the class
ready to receive, then why can't I reference it? Why does it work at
all (which though it is wrong, it is working)?

It does not appear that I should ever be able to pass a thread
*anything* with the "this" keyword as I can never reference back to the
"this" that I sent it. At least not the UI part of it. I am guessing I
could use other variable/controls' values on the form to make
calculations, just not physically updating a control on the form.

You can use the reference to your form (the fact that you passed it as
"this" in a method is irrelevant) but only in order to call Invoke,
BeginInvoke, InvokeRequired and CreateGraphics on it.

You could use other variables, but not controls, and you'd still need
to synchronize as you have to for all shared data.
 
J

jm

Willy Denoyette said:
Jon,

Sorry but it won't. just add a Form1_Closed (or FormClosing or TextChanged,
or whatever valid ) eventhandler and try to call Form.Close() from the
Notify context menu handler. Set a breakpoint in the eventhandler and you
will see it won't get called when run just run the message pump
(Application.Run()). Now call Run with a form reference, and you will see
that your handlers are getting called.
The reason for this is that the WM_XXXX messages can't get dispached to the
right window as there is NO window (no HWND, no GDI DC no GDI Region)
associated with the form.

Willy.

Alright, last one, this time I think it might be right. After much
searching, I found:

//in Form1

public class Form1 : System.Windows.Forms.Form
{
//define the delegate
public delegate void DelegateThreadFinished();

//create an instance of the delegate
public DelegateThreadFinished _threadFinished;
....

private void Form1_Load(object sender, System.EventArgs e)
{
_threadFinished = new DelegateThreadFinished(this.MyInvoker);
ThreadStart starter = new ThreadStart(this.DoStuff);
Thread t = new Thread(starter);
t.Start();
}

private void DoStuff()
{

clsListening myLis = new clsListening(this);
myLis.StartListening(this);

}

public void MyInvoker()
{

MessageBox.Show("ThreadInvoked...");
}


//Somewhere in the class clsListening

//invoke your thread
f._threadFinished();

It compiles, works and appears to be "threadsafe." Any comments are
welcome. Thanks.
 
J

jm

Willy Denoyette said:
Jon,

Sorry but it won't. just add a Form1_Closed (or FormClosing or TextChanged,
or whatever valid ) eventhandler and try to call Form.Close() from the
Notify context menu handler. Set a breakpoint in the eventhandler and you
will see it won't get called when run just run the message pump
(Application.Run()). Now call Run with a form reference, and you will see
that your handlers are getting called.
The reason for this is that the WM_XXXX messages can't get dispached to the
right window as there is NO window (no HWND, no GDI DC no GDI Region)
associated with the form.

Willy.

I take it back. That was doing the same thing I was already doing. I changed this:

//in my class that is the thread
f.Invoke(new EventHandler(f._threadFinished), new object[] {this, EventArgs.Empty});

//in Form1 I changed to this:

public delegate void DelegateThreadFinished(object sender, EventArgs e);

and then finally this:

public void MyInvoker(object sender, EventArgs e)

I believe this is finally correct. Thank you.
 
W

Willy Denoyette [MVP]

Jon Skeet said:
What if the form had had Show() called on it first? I didn't say that
you'd need to do something to show the form before starting the message
pump, which I meant to - but surely at that stage there *is* a HWND
etc. I haven't got time to test this at the moment, and it's not
terribly important, so don't worry if you don't have a lot of time to
explain :)

Jon,
Sure, it's not that important, only good to know :)
Calling 'Show' on the main thread associates the window with the form , the
HWND is now owned by the Form and the calling thread (HWND's have thread
affinity), and messages can be send/posted. However, while closing the form
successfully removes the form and owned window, it won't stop the message
loop, the main thread doesn't exit and the application appears to be hanging
(unless you call Application.Exit).

Willy.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top