简体   繁体   English

您可以向其订阅方法的单个线程,该线程将以无序方式执行

[英]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. 所有这些方法都可以有一个标头(例如(Object sender,EventArgs e))并返回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. 我提出了以下实现,它似乎完全满足了我的需要:基本上,我启动了一个内部线程,该线程每x毫秒触发一次事件。 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 . 您需要使_stop volatile In C# the event accessor methods are thread-safe so that works fine. 在C#中,事件访问器方法是线程安全的,因此效果很好。

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. 定义事件OnError并将错误报告给您的类的使用者。

You could use a timer or await Task.Delay to save a thread. 您可以使用计时器或await Task.Delay保存线程。 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: 在以下情况中,您有可能导致NullReferenceException的竞争条件:

    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 . if (_mainEvent != null)_mainEvent的调用之间, _mainEvent其他线程可以取消订阅该事件或调用Clear()

To avoid this, you should copy _mainEvent into a local variable and check that against null, and use that instead: 为了避免这种情况,您应该将_mainEvent复制到本地变量中,并检查是否为null,然后改用它:

    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. 无论如何,我认为您应该为此使用Timer而不是自己动手。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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