我不习惯使用AutoResetEvent
,并且想知道如何发生以下情况。
我们有一个日志文件,它始终在两台不同的计算机上记录不同的加载操作顺序:
机器A(发生问题)
Loading Module A Loading Module B Loading Shell. Show Window. Waiting Until Services are Loaded & Initialized. Loading Module C Starting Application ..
机器B(普通日志文件)
Loading Module A Loading Module B Loading Module C Starting Application .. Loading Shell. Show Window. Initializing Menu Elements ...
第一台机器从不加载菜单元素。
代码是这样的:
public class SplashScreen : Form
{
// SplashScreen.Run method which signals the ProgressCompleted event
private void Run()
{
// some code
MySingleton.Instance.ExecutionCompleted.WaitOne();
MySingleton.Instance.Completed = true;
MySingleton.Instance.ProgressCompleted.Set();
// more code
}
}
public class ShellApplication : FormShellApplication<WorkItem, ShellForm>
{
// ShellApplication.Start override
protected override void Start()
{
MySingleton.Instance.ProgressCompleted.WaitOne();
WriteToLog("Starting Application ..");
base.Start();
}
}
public class ShellForm : Form
{
// Background worker that runs from ShellForm.Load
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
// check to ensure services & ui components are loaded & initialized
if (!MySingleton.Instance.Completed)
{
WriteToLog("Waiting Until Services are Loaded & Initialized.");
MySingleton.Instance.ProgressCompleted.WaitOne();
}
}
// Background worker’s RunWorkerCompleted that runs from ShellForm.Load
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Some Code
WriteToLog("Initializing Menu Elements ...");
}
}
单身人士使用AutoResetEvent
ExecutionCompleted
和ProgressCompleted
,以及带有Completed
旗帜同步锁的布尔
public class MySingleton
{
private object _sync = new object();
private static AutoResetEvent _executionCompleted = new AutoResetEvent(false);
private static AutoResetEvent _progressCompleted = new AutoResetEvent(false);
private static bool _completed = false;
public AutoResetEvent ProgressCompleted
{
get
{
lock (_sync)
{
return _progressCompleted;
}
}
}
public AutoResetEvent ExecutionCompleted
{
get
{
lock (_sync)
{
return _executionCompleted;
}
}
}
public bool Completed
{
get
{
lock (_sync)
{
return _completed;
}
}
set
{
lock (_sync)
{
_completed = value;
}
}
}
}
从我所知道的,在机器A上看起来像后台工作程序在所有模块加载之前启动,并且ProgressCompleted.WaitOne()
在.Completed
标志为false时从未被命中或被命中。我没有足够的AutoResetEvent
经验来了解代码中的任何内容是否会导致此问题,例如第二次.WaitOne
调用它。
我不认为它是与同步锁有关的计时问题,因为它在机器A上每次都会一直发生,而我无法在机器B(我的机器)上重现问题。 / p>
上面的代码中是否有与AutoResetEvent
用法相关的任何可能导致此异常行为的内容?我正在使用.Net 3.5。
答案 0 :(得分:2)
您可能需要考虑使用ManualResetEvent
代替AutoResetEvent
。
重置事件就像一个红绿灯。由于您使用false
对其进行初始化,因此它会以红灯开始。
当你set
它时,它会变成绿色。
ManualResetEvent
和AutoResetEvent
之间的区别在于它保持绿色的时间......
ManualResetEvent
会保持绿色,直到有人打电话给Reset
。
AutoResetEvent
会让一辆车进入并再次自动恢复到红灯状态。
您设置ProgressCompleted
一次,但是等待两次,第一次在ShellApplication.Start
,第二次在worker_DoWork
。这意味着第二次等待将永远等待。
它永远不会失败的原因是因为if (!MySingleton.Instance.Completed)
指示如果启动画面代码比后台工作者快,则不会等待第二次重置事件