[英]A single thread to which you can subscribe methods, to be executed in an unordered fashion
我需要实现以下逻辑:
我提出了以下实现,它似乎完全满足了我的需要:基本上,我启动了一个内部线程,该线程每x毫秒触发一次事件。 您可以通过适当的方法订阅/取消订阅此事件的代表。
在坚持下去之前,我想知道采用这种方法是否可能存在细微问题。
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);
}
}
}
基本上没关系。 您需要使_stop
volatile
。 在C#中,事件访问器方法是线程安全的,因此效果很好。
异常处理非常有问题。 您是否真的要向控制台发送垃圾邮件? 定义事件OnError
并将错误报告给您的类的使用者。
您可以使用计时器或await Task.Delay
保存线程。 如果同时有很多这样的类实例,这将是有意义的。 如果只有一个,这可能不值得付出努力。
在以下情况中,您有可能导致NullReferenceException的竞争条件:
while(!_stop)
{
if (_mainEvent != null)
try
{
_mainEvent(this, new EventArgs());
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Thread.Sleep(_ms);
}
if (_mainEvent != null)
与_mainEvent
的调用之间, _mainEvent
其他线程可以取消订阅该事件或调用Clear()
。
为了避免这种情况,您应该将_mainEvent
复制到本地变量中,并检查是否为null,然后改用它:
var mainEvent = _mainEvent;
if (mainEvent != null)
try
{
mainEvent(this, new EventArgs());
无论如何,我认为您应该为此使用Timer而不是自己动手。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.