简体   繁体   中英

A single thread to which you can subscribe methods, to be executed in an unordered fashion

I need the following logic implemented:

  1. a thread to which you can subscribe/unsubscribe methods at runtime.
  2. It's fine for all these methods to have an header such as (Object sender, EventArgs e) and to return void.
  3. These methods scope must be the scope of the class where they are defined lexically .
  4. There's no guarantee about the order of execution

I've come up with the following implementation, which seems to do exactly what I need: basically I start an internal thread which triggers an event each x milliseconds. You can subscribe/unsubscribe delegates to this event through appropriate methods.

Before sticking to it I'd like to know if there may be subtle issues following this approach.

public class Orchestrator
{
    private Thread _mainThread;

    private event MethodDelegate _mainEvent;

    public delegate void MethodDelegate (Object sender, EventArgs e);

    private bool _stop = false;

    private short _ms = 100;
    public short PollingInterval { get { return _ms; }
        set
        {
            _ms = value;
        }
    }

    public Orchestrator()
    {
        _mainThread = new Thread(new ThreadStart(_execute));
    }

    public void Start()
    {
        _stop = false;
        _mainThread.Start();
    }
    public void Stop()
    {
        _stop = true;
    }

    public void Clear()
    {
        _mainEvent = null;
    }
    public void Push(MethodDelegate method)
    {
        _mainEvent += method;
    }
    public void Pop(MethodDelegate method)
    {
        _mainEvent -= method;
    }
    private void _execute()
    {
        while(!_stop)
        { 
            if (_mainEvent != null)
                try
                { 
                    _mainEvent(this, new EventArgs());
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }

            Thread.Sleep(_ms);
        }
    }
}

That's basically fine. You need to make _stop volatile . In C# the event accessor methods are thread-safe so that works fine.

The exception handling is very questionable. Do you really want to spam errors to the console? Define an event OnError and report errors to the consumer of your class.

You could use a timer or await Task.Delay to save a thread. This would make sense if there are a lot of such class instances at the same time. If there is just one this is likely not worth the effort.

You have a race condition which could cause a NullReferenceException, in:

    while(!_stop)
    { 
        if (_mainEvent != null)
            try
            { 
                _mainEvent(this, new EventArgs());
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

        Thread.Sleep(_ms);
    }

Some other thread could unsubscribe from the event or call Clear() inbetween if (_mainEvent != null) and the call of _mainEvent .

To avoid this, you should copy _mainEvent into a local variable and check that against null, and use that instead:

    var mainEvent = _mainEvent;
    if (mainEvent != null)
        try
        { 
            mainEvent(this, new EventArgs());

In any case, I think you should be using a Timer for this rather than rolling-your-own.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM