Link to home
Start Free TrialLog in
Avatar of mikezat
mikezat

asked on

Calling a method with params on a form on a different thread (C#)

Hi! I need to call a method with some parameters
on a form which was created on a different thread.

Here's how I create the form:
// In the Main Thread:

ThreadStart entryPoint = new ThreadStart(ShowSplashForm);
Thread splashFormThread = new Thread(entryPoint);
splashFormThread.Name = "Splash form thread";
splashFormThread.Start();
..................
public static frmSplash m_SplashForm;
public static void ShowSplashForm()
{
      m_SplashForm = new frmSplash();
      m_SplashForm.ShowDialog();
}

I can see that the form does get created on a new thread called "Splash form
thread"

Now the problem:
The frmSplash form has a public method called
public void UpdateCaption(string newCaption)

How do I call it from the main thread that created this form ?
Please provide the code for this example, not a link to google. I tried searching and examples I found either did not work or were not what I was looking for.

Many Thanks in Advance,

-- Mike
Avatar of jaguarul
jaguarul

You seem to keep a reference (m_SplashForm) to your form. Simply call the method from your main thread. In what way "it doesn't work"? Nothing happens? Crashes? Hangs? You might want to synchronize your two threads, so that you call "UpdateCaption" only after the form is created, but if that was the problem some runtime error would probabily appear.
Avatar of Julian Hansen
I agree with jaguarul,

The splash form exists outside of the thread - the thread is only creating and displaying the form so you should be able to simply do a

m_SplashForm.UpdateCaption ( "Almost There ..." )

but as Jaguarul says you need to synchronise your thread with the main thread or you could end up trying to update the Caption with a null m_SplashForm.

Sort of,

WaitForFormToBeCreated
m_SplashForm.UpdateCaption ( "Mostly Done ...")

HTH
Avatar of mikezat

ASKER

Hi! Thank you for looking into this. I am getting the following error when I tried this approach. That's why I posted this question here.

"An unhandled exception of type 'System.NullReferenceException' occurred in WindowsApplication2.exe

Additional information: Object reference not set to an instance of an object."


it occures when calling the splash form's UpdateCaption function:
m_SplashForm.UpdateCaption (pstrMessage);
This means (I think) that your ShowSplashForm code has not finished running and creating the form - m_SplashForm is NULL i.e. the

m_SplashForm = new frmSplash ()

either has not run or failed.

You should do a check on the object before hand to see if it has been instantiated and then either skip or enter some efficient wait state until the object has been created.

One option might be to block the main thread until you get some indication that the SplashThread has created the SplashForm. You could use a synchronisation object (someone please provide an exact C# example) that the main thread waits on and that the ShowSplashForm thread signals right after a successful create of the m_SplashForm object.

If you are unsure post back and I will try and do some code here to demonstrate what I and Jagual were referring to - don't have any off the top of my head.
ASKER CERTIFIED SOLUTION
Avatar of jaguarul
jaguarul

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
or just move the line where you create the form outside of the loop :-)

m_SplashForm = new frmSplash();
ThreadStart entryPoint = new ThreadStart(ShowSplashForm);
Thread splashFormThread = new Thread(entryPoint);
splashFormThread.Name = "Splash form thread";
splashFormThread.Start();
..................
public static frmSplash m_SplashForm;
public static void ShowSplashForm()
{
     m_SplashForm.ShowDialog();
}

now it should work! just a one line change :-)

Pratap
if synchronization is what you are looking for then take a look at Events -> manual and autoset

the classes ManualResetEvent and AutoResetEvent should help

basically you create the event object before you start the thread

AutoResetEvent ar=new AutoResetEvent()
Thread th=new Thread(new ThreadStart(ShowSplashForm));
th.Start();
ar.WaitOne();
//now you can use your m_splashform object

public frmSplash m_SplashForm;
public void ShowSplashForm()
{
     m_SplashForm = new frmSplash();
     //here
     ar.set(); //assuming ar is in scope
     m_SplashForm.ShowDialog();
     //or here
}

Enjoy!
Pratap
Pratap,

Looks good - I have one small question though

public void ShowSplashForm()
{
     m_SplashForm = new frmSplash();
     //here
     ar.set(); //assuming ar is in scope
     m_SplashForm.ShowDialog();
     //or here   <----- Is this a good idea?
}

Form would have to be modal - or else what is the purpose of the thread and if it is modal you would have to wait until the form exited before your main loop could proceed - am I correct?

i had put that so that a event can be set after the form is closed.. :-) say for example after a dialog result.. probably it should have been //and here.   :-)

Pratap
oic - yes that makes sense - need to know when the form has finished doing its thing.