Tech Off Thread

11 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

Invoke a Method That Runs On a Seperate Thread

Back to Forum: Tech Off
  • User profile image
    Shark_M

    Hello Guys,
    I have a problem here. The problem is that I have a main thread, the UI thread, and a workerThread on the background. I need the background thread to execute a method that runs in the Main UI thread. How do i do that?

    I have already made an event and its eventargs, in the workerthread, so when dataarrived, the event is raised, now i want the event handler to be a method that runs in the main UI thread. How is this done?

    thanks in advance

  • User profile image
    Minh

    this.Invoke(delegate)

    where "this" is your form. Invoke would insure that the thread that created your form (the UI thread) is used to run the delegate.

  • User profile image
    Shark_M

    what if the method is on a class, that is run on the main thread?

    class method running on one worker thread, and another main class that runs on the main UI thread. How do i invoke a method in the class that is running in the main process thread from the class that is run in the background worker thread?

  • User profile image
    Minh

    Shark_M wrote:
    what if the method is on a class, that is run on the main thread?

    class method running on one worker thread, and another main class that runs on the main UI thread. How do i invoke a method in the class that is running in the main process thread from the class that is run in the background worker thread?
    I'm not sure I follow ... perhaps you could post some code.

  • User profile image
    Shark_M

    I have a class called Connection,
    I also have another class called ReciverService , that tried to read data from the remoteend point, (networkstream.read) , and then pass the data read to a method in the Connection Class

    There is a method in the Connection class that deals with the datarecived.

    In the main form, i instantiated a new instance of the Connection class, and connect to the remote end point. When the connection is established, a new thread is started with the address of a method in the ReciverService, DoRecive method. this method loops through the networkstream, while .canread = true,  and tried to read data continusly from the remoteendpoint, and if there is datarecived it  pass that data back to the ConnectionClass's method called ProcessRecivedData.

    i made all, except the part where after the data is recived, how do i pass it back to the main thread that is executing the Connection class instance?

  • User profile image
    Minh

    Yes, it's .Net 1.1 -- and yes, it's very convoluted. I hear things are easier in .Net 2.0.


    public class MainForm : System.Windows.Forms.Form
    {
       private MyWorkerObj worker = new MyWorkerObj();
    
       private delegate void OnTaskDoneUIDelegate(MyCustomEventArgs args);
       private OnTaskDoneUIDelegate myDelegate = null;
       ...
    
       private void MainForm_Load(object sender, System.EventArgs e)
       {
          myDelegate = new OnTaskDoneUIDelegate(OnTaskDoneUI);
          worker.OnTaskDone +=new TaskDoneHandler(OnTaskDone);
    
          ...
          // After setting parameters required by DoTask()
          // This could be launched elsewhere too ... like a OnClick()
          ThreadPool.QueueUserWorkItem(new WaitCallback(worker.DoTask));
       }
    
       private void OnTaskDone(object sender, MyCustomEventArgs e)
       {
           object[] args = new object[1];
           args[0] = e;
    
           this.Invoke(myDelegate, args);
       }
    
       private void OnTaskDoneUI(MyCustomEventArgs e)
       {
          // Do UI related stuff here
          ...
       }
    
       ...
    }
    

  • User profile image
    Shark_M

    i managed to do the invoke for a delegate, but the Workerthread is the thread that processed the event, and not the main thread (UI)

    make new instance of a class, connection
    class connection
    public delegate sub ReciveDeletage (e as CutsomEventArgs)
    public mydelegate as new ReciveDelegate (AddressOf methodinvoker)
    public sub OnConnect ()
    Create new workerthread
    dim Reciver as new ReciverT
                            ReciverThread = New Thread(AddressOf ReciverT.BeginRecive)
                            ReciverThread.Name = "Reciver"
                            ReciverThread.IsBackground = True
                            ReciverThread.Start()

    .......
    end sub
    public sub MethodInvoker (e as customeeventargs)
        do somehting here on my thread (UI thread)
    end sub
    end class
    ====================================
    Class ReciverT
     public sub BeginRecive ()
    do some hardwork

    <Invoke the delegate on the mainthread and pass it some data >
    dim e as new CustomeEventArgs
    e.CustomeEventArgs = MyRecivedData
    ConectionInstance.MyDelegate.Invoke(e)           <<<<<<here>>>>

    end class



    The probem is at <here > line , when i invoke the delegate, by ClassNameInstance.Mydelegate.Invoke (e), the WorkerThread (holding the beginRecive Code), is the one that Goes to Execute the Method, that the delegate points to, and NOT the Main UI thread, holding the Instance of the Connection Class methods.

    why would invoke not go to the main thread ? the UI thread i mean?
    How do the UI thread, holding the instance of the Connection class, to execute the Method that mydelegate pointed to?

    I am stuck with this, and need some assisstance Sad

    please help

  • User profile image
    Shark_M

    now i am getting this error


    An error occurred creating the form. See Exception.InnerException for details.  The error is: ActiveX control '8856f961-340a-11d0-a96b-00c04fd705a2' cannot be instantiated because the current thread is not in a single-threaded apartment.


    any ideas aso to why this is happening?

  • User profile image
    Minh

    Shark_M wrote:

    public sub MethodInvoker (e as customeeventargs)
        do somehting here on my thread (UI thread)
    end sub

    [...]

    why would invoke not go to the main thread ? the UI thread i mean?


    You're thinking that just because a method is defined inside your form object, by calling it from a different thread, the system would switch to using the UI thread for execution. This is not the case.

    As you've already found out, the system continues to use your newly spawned (or ThreadPool) thread. In order to MAKE the system use the UI thread, your must make another "jump".

    Essentially, you must do a Me.Invoke(yetAnotherDelegate) in your MethodInvoker function. Me.Invoke ensures that yetAnotherDelegate will be executed using the thread that created "Me" -- which is the UI thread.

  • User profile image
    Minh

    Shark_M wrote:
    now i am getting this error


    An error occurred creating the form. See Exception.InnerException for details.  The error is: ActiveX control '8856f961-340a-11d0-a96b-00c04fd705a2' cannot be instantiated because the current thread is not in a single-threaded apartment.


    any ideas aso to why this is happening?


    This may have to do with adorning your Main entry point with the <STAThread> attribute. This tells the runtime to start your application with an STA thread -- which ActiveX controls like (or something to that effect)

  • User profile image
    ScanIAm

    I have used the following pattern to great success, although I haven't yet tried it with 2.0:

    public void function(arg1, arg2, ...)

    {

         if(this.InvokeRequired==true)

              this.Invoke(function,new object[] {arg1, arg2, ...});

         else

              ...do stuff here

    }

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.