2016-01-13 73 views
1

我不习惯与AutoResetEvent一起工作,我想知道如何发生以下情况。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 ..."); 
    } 
} 

的单用途为ExecutionCompletedProgressCompletedAutoResetEvent,并与同步锁布尔为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标志为fa伦敦政治经济学院。我没有足够的经验与AutoResetEvent知道是否有任何代码会导致此,如第二个.WaitOne调用它。

我不认为这是与同步锁有关的时间问题,因为它始终发生在机器A上的每一次,而我无法重现机器B(我的机器)上的问题。

以上代码中是否有与AutoResetEvent用法相关的任何内容,可能会导致此异常行为?我正在使用.Net 3.5。

回答

2

您可能要考虑使用ManualResetEvent而不是AutoResetEvent

重置事件就像一盏红绿灯。由于您将其初始化为false,因此会以红灯启动。 当你set它,它变成绿色。 ManualResetEventAutoResetEvent之间的差异是多少时间停留在绿色...

ManualResetEvent将保持绿色,直到有人调用它ResetAutoResetEvent将让一辆车进入并自动恢复为红灯。 您设置了ProgressCompleted一次,但您在其上等待两次,第一次在ShellApplication.Start,第二次在worker_DoWork。意味着第二次等待将永远等待。

它不会总是失败的原因是因为if (!MySingleton.Instance.Completed)这意味着如果启动画面代码比后台工作者快,您不会再次等待重置事件。

+0

谢谢!我怀疑这可能是这种情况,但我无法在网上找到任何具体示例......我不认为要将它与ManualResetEvent进行比较。我终于做了一个可以证实这一点的示例项目。我也喜欢你的汽车比喻:) – Rachel

相关问题