2016-01-13 33 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

相關問題