ManualResetEvent WaitOne не разблокируется - PullRequest
4 голосов
/ 30 июля 2009

Я немного сбит с толку из-за ManualResetEvent, которое я использую, которое, кажется, не разблокирует. Кто-нибудь знает, почему это может иметь место?

У меня есть сценарий такого рода. Реальная ситуация довольно сложна, и мне не удалось выделить фрагмент кода, который разумно опубликовать, чтобы воспроизвести проблему.

EDIT
Я обновил пример кода ниже. Это выполняется в ряде различных диалогов, и я заметил, что один из них попадает в this.mre.WaitOne (); Затем происходит диалоговое окно «Server Busy», где мне нужно нажать «switch to» или «retry», что позволит моему коду перейти на шаг WaitOne () и все будет работать. Я не уверен, насколько это уместно, но, очевидно, что-то важное.

public class A
{
 ManualResetEvent mre;

 public void Start(ThreadClass tc)
 {
    this.mre = new ManualResetEvent(false);
    tc.Begin();

    WebClient wc = new WebClient();
    // progress events are pumped to the ThreadClass which then update the Form2.
    wc.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(wc_DownloadFileCompleted);

    wc.DownloadFileAsync("Src", "Tgt");
    this.mre.WaitOne();
 }

 void void wc_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
 {
    try
    {
     // Do Stuff
    }
    finally
    {
      this.mre.Set();
    }
 }
}

public class ThreadClass
{
   Begin()
   {
      Thread t = new Thread(new ThreadStart(DoWork));
      t.Start();
   }

   private void DoWork()
   {
     Form f = new Form2();
     f.ShowDialog();

     // Sits waiting on another ResetEvent to determine when to close the thread.
   }
}

Ответы [ 4 ]

4 голосов
/ 30 июля 2009

Webclient работает в том же потоке, что и ваш вызывающий, так что поток блокируется в WaitOne, он фактически не создает новый поток для вас.

Переместите свой код в BackgroundWorker или просто не блокируйте, а дождитесь возникновения события DownloadComplete.

3 голосов
/ 30 июля 2009

Убедитесь, что MRE, которое вы устанавливаете, на самом деле совпадает с MRE, на котором вы ожидаете. Вы говорите, что это упрощенный пример - возможно ли, что в коде real вы создаете два разных события сброса? Это довольно очевидно сломало бы вещи:)

2 голосов
/ 10 июня 2010

Я немного изменил ваш код, и теперь он будет работать так, как предполагалось. Проблема заключалась в том, что вы должны были передать объект MRE в качестве параметра состояния пользователя метода DownloadFileAsync:

public class A 
{  
 public void Start(ThreadClass tc) 
 { 
    ManualResetEvent mre = new ManualResetEvent(false);
    WebClient wc = new WebClient(); 
    // progress events are pumped to the ThreadClass which then update the Form2. 
    wc.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(wc_DownloadFileCompleted); 

    wc.DownloadFileAsync("Src", "Tgt", mre); 
    mre.WaitOne();
    mre.Close();
 } 

 void void wc_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) 
 { 
    try 
    { 
     // Do Stuff 
    } 
    finally 
    { 
      (e.UserState as ManualResetEvent).Set();
    } 
 } 
} 
1 голос
/ 30 июля 2009

Почему бы не использовать wc.DownloadFile вместо wc.DownloadFileAsync, если вы хотите, чтобы он все равно блокировался ..

...