c# - 超时时间为 0 的 ManualResetEvent.WaitOne() 返回意外错误,尽管已设置事件
问题描述
我有一个包装类ManualResetEvent
(见下面的代码示例)
在我的应用程序流程中,我多次WaitOne
使用参数调用该方法。0
它true
按预期返回,除了一个特定的检查返回,false
尽管没有引发异常,我可以从我的日志中清楚地看到该事件已设置。
是否还有其他理由WaitOne
返回false
?
我还将提到我有 2 个不同的引擎从具有SafeManualResetEvent
成员的同一引擎继承。让我们打电话给他们A
和B
。流程就是这样A.SafeManualResetEvent
设置的,并且几次调用A.WaitOne(0)
返回 true。然后,B.Set()
被调用并完成。然后,A.WaitOne(0)
再次调用并返回false
。
之后,所有A.WaitOne(0)
并按预期B.WaitOne(0)
返回。true
有没有可能这两个实例ManualRestEvent
互相干扰?
我在这里添加了一个非常抽象的示例。请注意,waitOne 调用可以来自我们应用程序中的不同线程。另请注意,此问题并非始终如一地发生。在运行这个应用程序的数千名用户中,只有一个人抱怨它,但我们仍在努力找出他的环境有什么不同。
public void Main()
{
PolicyEngine policy = new PolicyEngine();
policy.WaitEngine(); //will return true because initial state is true
policy.LoadEngine();
policy.WaitEngine(); //will return true
FileEngine file = new FileEngine();
policy.WaitEngine(); //will return true
file.LoadEngine();
policy.WaitEngine(); //returns false - unexpected!
policy.WaitEngine(); //returns true
file.WaitEngine(); //returns true
}
public class Engine
{
protected virtual string GetName()
{
return "base";
}
private readonly SafeManualResetEvent _engineLoadedEvent = new SafeManualResetEvent(true);
public Engine()
{
_engineLoadedEvent._name = GetName();
Console.WriteLine("base");
}
public void LoadEngine()
{
_engineLoadedEvent.Reset();
//some code that loads the engine
_engineLoadedEvent.Set();
}
public void WaitEngine()
{
bool result = _engineLoadedEvent.WaitOne(new TimeSpan(0));
Console.WriteLine($"waitOne result is: {result}");
}
}
public class FileEngine : Engine
{
override protected string GetName()
{
return "file";
}
}
public class PolicyEngine : Engine
{
override protected string GetName()
{
return "policy";
}
}
public class SafeManualResetEvent : IDisposable
{
public string _name;
public SafeManualResetEvent(bool initialState)
{
ManualResetEvent = new ManualResetEvent(initialState);
}
public ManualResetEvent ManualResetEvent { get; }
public bool WaitOne(TimeSpan timeout)
{
try
{
Console.WriteLine($"waitOne event for {_name}");
return ManualResetEvent.WaitOne(timeout);
}
catch (ObjectDisposedException)
{
return false;
}
}
public void Reset()
{
try
{
Console.WriteLine($"reset event for {_name}");
ManualResetEvent.Reset();
}
catch (ObjectDisposedException)
{
}
}
public void Set()
{
try
{
Console.WriteLine($"set event for {_name}");
ManualResetEvent.Set();
}
catch (ObjectDisposedException)
{
}
}
public void Dispose()
{
Console.WriteLine($"dispose event for {_name}");
ManualResetEvent.Dispose();
}
}
解决方案
推荐阅读
- excel - VBA 上的运行时错误“13”-我该如何解决?
- r - 如何制作多面华夫饼图,从左上角填充每个箱子
- amazon-web-services - AWS DynamoDB 插入多个属性
- node.js - 即使我有 JSON 数据,数据也没有从 mongoDB 拉到我的图表中
- iis - IIS 对任何请求返回 200 OK
- python - 如何修复python类中的属性错误
- ruby-on-rails - 在 Active Storage 的 ImageProcessing 转换器中弃用 combine_options
- api - Imgur 无法上传“消息”:“剥离元数据失败”
- php - curl 抓取单个网站两层深度
- python - python - 如何在不改变python中图片的原始形状的情况下将带有openCV的图片调整为固定大小?