Forms, threads, and BeginInvoke

  • Thread starter Thread starter Tim Clark
  • Start date Start date
T

Tim Clark

Can someone explain this to me. I have a function that is called
asynchronously using a delegate, which has a callback function. In the
callback function, I want to create a new form. However, the call to
BeginInvoke on the delegate creates a new thread which the form is
attached to. This causes the form to not receive any events because
there is no messsage loop set up on that thread. Of course, I COULD do
Application.Run for this new form, but I don't WANT to do that. I
would LIKE the form to run in the same thread as the thread that
called the async method. Now, my question is, how can I have the same
behaviour as the File IO Stream classes? They have methods called
BeginRead which takes an async callback, but this does NOT create a
new thread. If I use the line commented out
(System.IO.File.OpenRead...etc) below, then the form gets created in
the main threads context and everything works fine. So...does anyone
know how the Stream IO classes are able to do this? I've checked the
documentation, but I've only seen them talking about BeginInvoke. Is
there another way? I'm aware of Control.Invoke, but I don't want to
have to have a reference to a control. BeginRead doesn't seem to need
this. How do they do it?


public delegate void someCallBack();


void callback(IAsyncResult ar)
{
new Form1().Show();
}

void dosomething()
{
//do something...
}

private void button1_Click(object sender, System.EventArgs e)
{
//The line below WORKS!
//System.IO.File.OpenRead("C:\\somefile").BeginRead(new
byte[100],1,0,new AsyncCallback(callback),null);

someCallBack scb = new someCallBack(dosomething);
//this line does NOT work
scb.BeginInvoke(new AsyncCallback(callback),null);
}
 
Hey Tim

Your file example does NOT run asynchronously which is why your callback-function runs on the main thread. To enable asynchronous reads using FileStream.BeginRead, you must use on of the FileStream constructors where you can specify the useAsync parameter. In that case the callback-function will run on a separate thread (and you will not be able to show your form in the callback-function)

I think the easiest solution is to pass a reference to a control. All controls implement ISynchronizeInvoke so you can pass a reference to an implementation of this interface instead of to the control itself

Regards, Jakob
 
Yep, you're absolutely right. It's funny cause I read about 10 times in
the docs that you need to use the right constructor to get async, and my
brain just didn't process it! :)

I ended up goign with a reference to a form.

Thanks for the help!
 
Back
Top