Hi guys.
Im having a problem with this.
I have an object that i create in other thread. Now what i want to do, is that when i close my app in the event it must call a method from the object created in the thread maded earlier.
How can i do this? I ve tried calling just the object by its name but it doesnt work.
Thanks

Dani AI

Generated

created the worker object inside the worker thread (the run() method), which is why socketConectado.METHOD() from the closing event appears to “not work”: the main thread may see a null reference or the call may need to run on the worker thread itself. Two distinct approaches cover the usual needs.

First, if the main thread simply needs a safe reference to call thread-safe methods on the object, publish the reference safely and signal when it’s ready. For example, create a shared field, publish it with Interlocked.Exchange (or under a lock/Volatile.Write) and use a ManualResetEventSlim to wait briefly in the close handler before calling the cleanup method. Make the cleanup method itself thread-safe so it can be called from the closing thread without race conditions.

private ConectadoThread socketConectado;
private ManualResetEventSlim created = new ManualResetEventSlim();

// worker thread: create and publish
var local = new ConectadoThread();
Interlocked.Exchange(ref socketConectado, local);
created.Set();
local.RunLoop();

// closing: wait then call a thread-safe stop/close
if (created.Wait(2000)) {
  var sc = Interlocked.Exchange(ref socketConectado, null);
  sc?.RequestStop(); // RequestStop signals the worker to shutdown safely
}

Second, if the method must execute on the worker thread (not just be invoked from another thread), change the worker to accept commands: a ConcurrentQueue<Action> plus an AutoResetEvent (or BlockingCollection<T>). Expose a Post(Action) or EnqueueCommand(...) method that enqueues the delegate and signals the worker; the worker loop dequeues and runs commands on its own thread. This pattern avoids cross-thread invocation and deadlocks.

Also note points from earlier replies: ’s idea of passing parameters into threads is valid (pass objects or create them before starting the thread), and ’s warning about UI marshalling stands—use Control.Invoke/Dispatcher.Invoke (or SynchronizationContext) only when the method touches UI components. Avoid blocking the UI on shutdown; prefer signalling with timeouts and graceful shutdown; in modern code prefer Task + CancellationToken for cleaner cancellation semantics.

Recommended Answers

All 3 Replies

Please show us your code work. You should have to use Parameterized Thread.

If you are trying to marshal a call to the GUI thread it depends -- Is it a windows form or WPF application? Winforms use Control.Invoke() while WPF uses Dispather.Invoke() .

Here is a recent thread with a similar question, using winforms:
http://www.daniweb.com/forums/thread318221.html

If you're wanting to marshal the call a non-GUI thread you need to implement ISynchronizeInvoke . IDesign has an example of an ISynchronizeInvoke implementation:

Taken from idesign:

// © 2005 IDesign Inc. All rights reserved 
//Questions? Comments? go to 
//http://www.idesign.net

using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
using System.Security.Permissions;

[Serializable]
internal class WorkItem : IAsyncResult
{
   object[] m_Args;
   object m_AsyncState;
   bool m_Completed;
   Delegate m_Method;
   ManualResetEvent m_Event;
   object m_MethodReturnedValue;
   internal WorkItem(object AsyncState,Delegate method,object[] args)
   {
      m_AsyncState = AsyncState;
      m_Method = method;
      m_Args =  args;
      m_Event = new ManualResetEvent(false);
      m_Completed = false;
   }
   //IAsyncResult properties 
   object IAsyncResult.AsyncState
   { 
      get
      {
         return m_AsyncState;
      }
   }
   WaitHandle IAsyncResult.AsyncWaitHandle
   { 
      get
      {
         return m_Event;
      }
   }
   bool IAsyncResult.CompletedSynchronously
   {
      get
      {
         return false;
      }
   }
   bool IAsyncResult.IsCompleted
   { 
      get
      {
         return Completed;
      }
   }
   bool Completed
   {
      get
      {
         lock(this)
         {
            return m_Completed;
         }
      }
      set
      {
         lock(this)
         {
            m_Completed = value;
         }
      }
   }

   //This method is called on the worker thread to execute the method
   internal void CallBack()
   {
      MethodReturnedValue = m_Method.DynamicInvoke(m_Args);
      //Method is done. Signal the world
      m_Event.Set();
      Completed = true;
   }
   internal object MethodReturnedValue
   {
      get
      {
         lock(this)
         {
            return m_MethodReturnedValue;
         }
      }
      set
      {
         lock(this)
         {
            m_MethodReturnedValue = value;
         }
      }

   }
}
[SecurityPermission(SecurityAction.Demand,ControlThread = true)]
public class Synchronizer: ISynchronizeInvoke,IDisposable
{
   WorkerThread m_WorkerThread;
   public bool InvokeRequired 
   {
      get
      {
         bool res = Thread.CurrentThread.ManagedThreadId == m_WorkerThread.ManagedThreadId;
         return  ! res;
      }
   }
   public IAsyncResult BeginInvoke(Delegate method, object[] args)
   {
      WorkItem result = new WorkItem(null,method,args);
      m_WorkerThread.QueueWorkItem(result);
      return result;
   }
   public object EndInvoke(IAsyncResult result)
   {
      result.AsyncWaitHandle.WaitOne();
      WorkItem workItem = (WorkItem)result;
      return  workItem.MethodReturnedValue;
   }
   public object Invoke(Delegate method, object[] args)
   {
      IAsyncResult asyncResult;
      asyncResult = BeginInvoke(method,args);
      return EndInvoke(asyncResult);
   }
   public Synchronizer()
   {
      m_WorkerThread = new WorkerThread(this);
   }
   ~Synchronizer()
   {
   }
   public void Dispose()
   {
      m_WorkerThread.Kill();
   }
   internal protected class WorkerThread 
   {
      public Thread m_ThreadObj;
      bool m_EndLoop;
      Mutex m_EndLoopMutex;
      AutoResetEvent m_ItemAdded;
      Synchronizer m_Synchronizer;
      Queue<WorkItem> m_WorkItemQueue;

      public int ManagedThreadId
      {
         get
         {
            return m_ThreadObj.ManagedThreadId;
         }
      }

      internal void QueueWorkItem(WorkItem workItem)
      {
         lock(m_WorkItemQueue)
         {
            m_WorkItemQueue.Enqueue(workItem);
            m_ItemAdded.Set();
         }
      }
      internal WorkerThread(Synchronizer synchronizer)
      {
         m_Synchronizer = synchronizer;
         m_EndLoop = false;
         m_ThreadObj = null;
         m_EndLoopMutex = new Mutex();
         m_ItemAdded = new AutoResetEvent(false);
         m_WorkItemQueue = new Queue<WorkItem>();
         CreateThread(true);
      }
      bool EndLoop
      {
         set
         {
            m_EndLoopMutex.WaitOne();
            m_EndLoop = value;
            m_EndLoopMutex.ReleaseMutex();
         }
         get
         {
            bool result = false;
            m_EndLoopMutex.WaitOne();
            result = m_EndLoop;
            m_EndLoopMutex.ReleaseMutex();
            return result;
         }
      }
      Thread CreateThread(bool autoStart)
      {
         if(m_ThreadObj != null)
         {
            Debug.Assert(false);
            return m_ThreadObj;
         }
         m_ThreadObj = new Thread(Run);
         m_ThreadObj.Name = "Synchronizer Worker Thread";
         if(autoStart == true)
         {
            m_ThreadObj.Start();
         }
         return m_ThreadObj;
      }
      void Start()
      {
         Debug.Assert(m_ThreadObj != null);
         Debug.Assert(m_ThreadObj.IsAlive == false);
         m_ThreadObj.Start();
      }
      bool QueueEmpty
      {
         get
         {
            lock(m_WorkItemQueue)
            {
               if(m_WorkItemQueue.Count > 0)
               {
                  return false;
               }
               return true;
            }
         }
      }
      WorkItem GetNext()
      {
         if(QueueEmpty)
         {
            return null;
         }
         lock(m_WorkItemQueue)
         {
            return m_WorkItemQueue.Dequeue();
         }
      }
      void Run()
      {
         while(EndLoop == false)
         { 
            while(QueueEmpty == false)
            {
               if(EndLoop == true)
               {
                  return;
               }
               WorkItem workItem = GetNext();
               workItem.CallBack();
            }
            m_ItemAdded.WaitOne();
         }
      }
      public void Kill()
      { 
         //Kill is called on client thread - must use cached thread object
         Debug.Assert(m_ThreadObj != null);
         if(m_ThreadObj.IsAlive == false)
         {
            return;
         }
         EndLoop = true;
         m_ItemAdded.Set();

         //Wait for thread to die
         m_ThreadObj.Join();
         if(m_EndLoopMutex != null)
         {
            m_EndLoopMutex.Close();
         }
         if(m_ItemAdded != null)
         {
            m_ItemAdded.Close();
         }
      }
   }
}
commented: Awesome! +11

I will post my code, so you can tell me if i have to use isynchronizeinvoke or what.

In Form1:

thread = new Thread(run);
thread.Start();  
   
 public void run()
        {
            socketConectado = new ConectadoThread(); 
        }

Now, i want to call a method of "socketConectado".
How can i do this?
I cant just put socketConectado.METHOD()

Thanks

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.