我对我正在使用的看起来没有解锁的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.
}
}
答案 0 :(得分:4)
Webclient在与调用者相同的线程中运行,因此该线程在WaitOne处被阻止,它实际上并不为您创建新线程。
将您的代码移到BackgroundWorker中,或者只是,不要阻止,而是等待引发DownloadComplete事件。
答案 1 :(得分:3)
检查您设置的MRE是否与您正在等待的MRE相同。你说这是一个简化的例子 - 你可能在真正的代码中创建了两个不同的重置事件吗?这显然会破坏事情:)
答案 2 :(得分: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();
}
}
}
答案 3 :(得分:1)
为什么不使用wc.DownloadFile而不是wc.DownloadFileAsync,如果你想要阻止它..