seems a little bit impression, what’s the hell of Thread Message Loop.

  • Use Case – we have a STA DLL, which is exposed for us several COM/COM+ methods. And internally such DLL will store internal “status” cache, for instance STA instance, SA&G.
  • Key Points
  1. Explicit STA Thread construction – Thread.setApartment(STA/MTA). MTA is default setting.
  2. Supposed we call start(), and stop() for default instantiation logic of DLL, how about additional method called inside thread? Can we? Yes, just do something like Message loop. When performance has been concerned, EventWaitHandle (Mutex, Sep. etc)….

public class MethodProxyInThread
{
public MethodProxyInThread _realProxy;

private bool _isRealProxyStop = false;

private event EventHandler<EventArgs> _eventHandler;

private ThreadLocal<EventHandler<EventArgs>> _handler;

private Func<object, int> _functionalHook;

private EventWaitHandle waitHandle;

private object parameter;

/// <summary>
/// in one thread context
/// </summary>
/// <param name=”_realProxy”></param>
public void startMethod(object _realProxy)
{
if (this._realProxy == null)
{
this._realProxy = _realProxy as MethodProxyInThread;
this._isRealProxyStop = false;
Console.WriteLine(string.Format(“startMethod – {0}”, Thread.CurrentThread.ManagedThreadId));
Console.WriteLine(“startMethod”);

waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
this._handler = new ThreadLocal<EventHandler<EventArgs>>(() => new EventHandler<EventArgs>(this.MethodProxyInThread__eventHandler));
this._eventHandler += this._handler.Value;

//TODO : Call start Method Here
//startCall() here
do
{
Console.WriteLine(string.Format(“loopMethod – {0}”, Thread.CurrentThread.ManagedThreadId));
if (this.waitHandle.WaitOne(5000))//rest if no more action, what time-out? to avoid deadlock!
{
//TODO : invoke conditional method; -> parameters
this._functionalHook.Invoke(this.parameter);//, null, null); //=>asynchorous logic
if (!this._isRealProxyStop)
{
this.waitHandle.Reset();
}
}
} while (!this._isRealProxyStop);
//stopCall() here
this._eventHandler -= this._handler.Value;
this.waitHandle.Close();
Console.WriteLine(“Quit the thread”);
}
}

private void MethodProxyInThread__eventHandler(object obj, EventArgs e) //Guys, why this isn’t working, delegation will be running in ThreadPool
{
Console.WriteLine(string.Format(“MethodProxyInThread__eventHandler – {0}”, Thread.CurrentThread.ManagedThreadId));
this._isRealProxyStop = true;
}

//public void PostTerminalEvent()
//{
//    if (MethodProxyInThread._eventHandler != null)
//    {
//        Console.WriteLine(string.Format(“PostTerminalEvent – {0}”, Thread.CurrentThread.ManagedThreadId));
//        MethodProxyInThread._eventHandler(this, new EventArgs());
//    }
//}

public void PostMessage(Func<object, int> _func, object _param)
{
if (!this._isRealProxyStop)
{
this._functionalHook = _func;
this.parameter = _param;

this.waitHandle.Set();
}
}

public void stopMethod()
{
Console.WriteLine(string.Format(“stopMethod – {0}”, Thread.CurrentThread.ManagedThreadId));
this._isRealProxyStop = true;
}
}

class Program
{
static int PostMessageObj(object _obj)
{
Console.WriteLine(string.Format(“postMethod – {0}”, Thread.CurrentThread.ManagedThreadId));
return 5;
}

static void Main(string[] args)
{
MethodProxyInThread proxy = new MethodProxyInThread();
Thread t = new Thread(proxy.startMethod);
t.Start(proxy);

Thread.Sleep(5000);
proxy.PostMessage(new Func<object, int>(Program.PostMessageObj), 6);
Thread.Sleep(5000);
proxy.stopMethod();
//proxy.PostTerminalEvent();
Thread.Sleep(10000);
}
}

 

Of Course, that’s not the ultimate version, For Message Loop, we need dictionary<enum, Func<object, object>> for checking-up, and parameter lists.

Like it, or some more suggestions… Whatever :-). No-UI SynchronizationContext Solution.

Advertisements