5

我对我正在使用的 ManualResetEvent 有点困惑,它似乎没有解除阻塞。有谁知道为什么会这样?

我遇到的情况是这样的。实际情况非常复杂,我没有设法隔离一段可以合理发布以重现问题的代码。

编辑
我已经更新了下面的代码示例。这是在许多不同的对话框中执行的,我注意到其中一个点击了 this.mre.WaitOne(); 然后会发生一个“服务器忙”对话框,我需要在其中按“切换到”或“重试”,这将允许我的代码逐步通过 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 回答 4

4

Webclient 与您的调用者在同一个线程中运行,因此该线程在 WaitOne 处被阻塞,它实际上并没有为您创建一个新线程。

将您的代码移动到 BackgroundWorker 中,或者简单地说,不要阻塞而是等待引发 DownloadComplete 事件。

于 2009-07-30T10:20:33.667 回答
3

检查您设置的 MRE 是否与您正在等待的 MRE 相同。你说这是一个简化的例子——在真实的代码中你是否有可能创建两个不同的重置事件?这显然会破坏事情:)

于 2009-07-30T10:35:36.367 回答
2

我已经对您的代码进行了一些修改,它现在可以正常工作。问题是您应该将 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();
    } 
 } 
} 
于 2010-06-10T14:41:51.080 回答
1

如果您希望它无论如何都被阻止,为什么不使用 wc.DownloadFile 而不是 wc.DownloadFileAsync ..

于 2009-07-30T10:23:03.537 回答