ManualResetEvent WaitOne not unblocking

2019-05-07 12:20发布

问题:

I'm a little confused over a ManualResetEvent that I'm using which doesn't appear to be unblocking. Anyone know why this might be the case?

The scenario I've got is something along these lines. The real situation is quite complicated and I've not managed to isolate a section of code that's reasonable to post to reproduce the issue.

EDIT
I've updated the code example below. This is execute in a number of different dialogs and I have noticed that one of them hits the this.mre.WaitOne(); Then what happens is I get a "Server Busy" dialog, where I need to press 'switch to' or 'retry', which will then allow my code to step passed the WaitOne() call and all will work. I'm not sure how its relevant, but obviously its of some important.

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.
   }
}

回答1:

Webclient runs in the same thread as your caller, so that thread is blocked at the WaitOne, it doesn't actually create a new thread for you.

Move your code into a BackgroundWorker or simply, don't block but wait for the DownloadComplete event to be raised.



回答2:

Check that the MRE you're setting is actually the same MRE you're waiting on. You say this is a simplified example - is it possible that in the real code you're creating two different reset events? That would fairly obviously break things :)



回答3:

I have modified your code a bit and it will work as supposed to now. The problem was that you should have passed the MRE object as the user state parameter of the DownloadFileAsync method:

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();
    } 
 } 
} 


回答4:

Why not use wc.DownloadFile instead of wc.DownloadFileAsync if you want it to block anyways..