Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Windows Forms / WinForm General / July 2006

Tip: Looking for answers? Try searching our database.

Main thread calling event from child thread without using Ctrl.Inv

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Noulouk - 03 Jul 2006 15:21 GMT
Hi ,

I build an object with a method and an event.
In the method, I start a thread(child thread) and after a long process, the
event is raised (from the child thread unfortunately).

When I use this object in my form (main UI thread), I get an error which
tells me to use Textbox.Invoke (which I understand and I know how to solve
the error from my form). No problem.

The problem is I want the event to be raised in main thread, so no
Textbox.Invoke error will be thrown in my form.
I mean when the child thread wants to raise the event, I want to tell to use
the main thread of my object instead of the child thread.
So  no Textbox.Invoke required in my main UI thread.

Thanks in advance for your help.
Dan Manges - 03 Jul 2006 16:26 GMT
> Hi ,
>
[quoted text clipped - 13 lines]
>
> Thanks in advance for your help.

If I understand your problem correctly, you should be able to have a
method in your class which will raise the event, and then invoke that
method from the other thread.

A not-guaranteed-to-compile example:

public class Program
{
    public delegate void SomeHandler();
    public event SomeHandler OnEvent;

    private delegate void NoArgCallback();

    public void RaiseEvent()
    {
        if (OnEvent != null)
            OnEvent();
    }

    public void StartThread()
    {
        Thread thread = new Thread(new ThreadStart(ThreadMethod));
        thread.Start();
    }

    private void ThreadMethod()
    {
        NoArgCallback callback = new NoArgCallback(RaiseEvent);
        this.Invoke(callback);
    }
}

This will raise the event from the UI thread.

Hope this helps.

Dan Manges
Stoitcho Goutsev (100) - 04 Jul 2006 21:22 GMT
Dan,

To work your sample the class Program needs to inherit from Control.
Otherwise there is no Invoke method that will marshal the method call.
Delegates has Invoke also, but Control.Invoke and BeginInvoke are the only
methods that marhal the method calls to the UI thread. For some reason the
original poster doesn't want to use Control.Invoke.

BTW .NET 2.0 has BackgroundWorker component that is capable to marshal its
events to the UI thread without the requirements of a control. I've peeked
in the code there, but had no time to get too deep to understand how it
actually does this.

Signature

HTH
Stoitcho Goutsev (100)

>> Hi ,
>>
[quoted text clipped - 51 lines]
>
> Dan Manges
Dan Manges - 05 Jul 2006 01:57 GMT
> Dan,
>
[quoted text clipped - 8 lines]
> in the code there, but had no time to get too deep to understand how it
> actually does this.

Stoitcho,

Thanks for pointing that out.  I wrote that code like it was a
System.Windows.Forms.Form class, but I forgot to write that.

Dan Manges
Techno_Dex - 03 Jul 2006 16:55 GMT
In your EventHandler which is catching the Event Raised from the Child
Thread, call another method which will call itself if not currently
processing on the UI Thread, then handle your code or raise a new event from
there.

private void ChildThread_EventHandler(object sender, EventArgs e)
{
   DoWork(e);
}

private void DoWork(EventArgs e)
{
    //Check To see if you are currently running on the UI Thread or not, If
not, use the Generic MethodInvoker
    //to create a Delegate to call a method on the UI Thread (In this case,
the same Method only on the UI Thread)
    if (this.InvokeRequired == true)
   {
       MethodInvoker miMethodInvoker = new MethodInvoker(DoWork);
       //If the DoWork Method did not take in the EventArgs or any params
from the ChildThread, this you would use this.
       //miMethodInvoker.BeginInvoke(null, null);
       miMethodInvoker.BeginInvoke(null, new object[] (e});
       return;
   }

   //If you get to this point you are now on your UI Thread and you can
update your TextBox as needed or raise a new event.
   tbTextBox.Text = e.Value;
}

> Hi ,
>
[quoted text clipped - 15 lines]
>
> Thanks in advance for your help.
Noulouk - 03 Jul 2006 18:03 GMT
> When I use this object in my form (main UI thread), I get an error which
> > tells me to use Textbox.Invoke (which I understand and I know how to solve
> > the error from my form). No problem.
As you can read I know how to solve this problem and that's your answer.

I'm sorry if I have also problems to expose this problem. lol

In fact, don't mind about the main UI thread.
Let's focus on my object: this object when it is instanciated runs inside a
thread. I start a child thread with an object method. An event is raised
inside the child thread, but I want this event to be raised inside its parent
thread (object thread).

internal class TestClass
   {
       public event EventHandler MyEvent;

       public void MyMethod()
       {
           Thread.CurrentThread.Name = "Main";
           Thread child = new Thread(new ThreadStart(ChildMethod));
           child.Start();
      }

       void RaiseEvent( object sender, EventArgs e )
       {
           Console.WriteLine("On thread: " + Thread.CurrentThread.Name);
           if ( MyEvent != null )
               MyEvent( sender, e );
       }

       private void ChildMethod()
       {
       // some job
           RaiseEvent(this, null); //on child thread. I want to raise this
event  on parent Main thread
       // some job
       }
   }

Hope you see what I need.

> In your EventHandler which is catching the Event Raised from the Child
> Thread, call another method which will call itself if not currently
[quoted text clipped - 46 lines]
> >
> > Thanks in advance for your help.
Dan Manges - 03 Jul 2006 18:19 GMT
[snip]
>         private void ChildMethod()
>         {
[quoted text clipped - 6 lines]
>
> Hope you see what I need.
[snip]

Why can't you use an Invoke method from ChildMethod() to call RaiseEvent() ?

Dan Manges
Stoitcho Goutsev (100) - 04 Jul 2006 21:30 GMT
Noulouk,

I don't think you can pull this off without using Control.Invoke.
BackgroundWorker from .NET 2.0. does that and if you have enough time you
can dig into its code to find out how it does it.
My suggestion is to do the same that System.Timers.Timer component does.
This class has a property called SynchronizingObject of type
ISynchronizeInvoke. If an object implements this interface it has to make
sure that the call is marshaled to appropriate thread if necessary. At the
moment only the Control class implement this interface.

When your object needs to fire the event it checks whether the property is
set if it is, it uses objects Invoke method otherwise it fires the event in
the usual way.

Signature

HTH
Stoitcho Goutsev (100)

> > When I use this object in my form (main UI thread), I get an error which
>> > tells me to use Textbox.Invoke (which I understand and I know how to
[quoted text clipped - 98 lines]
>> >
>> > Thanks in advance for your help.

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.