ManualResetEvent WaitOne não desbloqueio
-
05-07-2019 - |
Pergunta
Estou um pouco confuso sobre um ManualResetEvent que eu estou usando o que não parece ser desbloqueio. Alguém sabe por que isso pode ser o caso?
O cenário que eu tenho é algo ao longo destas linhas. A situação real é bastante complicado e eu não conseguiram isolar uma secção de código que é razoável para deixar de reproduzir o problema.
Editar
Eu atualizei o exemplo de código abaixo. Este é executado em um número de diferentes diálogos e tenho notado que um deles bate no this.mre.WaitOne (); Então o que acontece é que eu obter um diálogo "Servidor ocupado", onde eu preciso de imprensa 'switch para' ou 'repetição', que permitirá então que meu código para etapa passou a chamada WaitOne () e todo o trabalho vontade. Não tenho certeza como a sua relevância, mas, obviamente, o seu de algum importante.
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.
}
}
Solução
Webclient é executado no mesmo segmento como o seu interlocutor, para que segmento está bloqueado no WaitOne, ele realmente não criar um novo segmento para você.
Mova seu código em um BackgroundWorker ou simplesmente, não bloqueie mas aguardar o evento DownloadComplete a ser levantada.
Outras dicas
Verifique se o MRE você está definindo é realmente o mesmo MRE você está esperando. Você diz que este é um exemplo simplificado - é possível que no real código que você está criando dois eventos de reposição diferentes? Isso seria bastante obviamente quebrar coisas:)
Eu modifiquei o código um pouco e ele vai funcionar como deveria agora. O problema era que você deve ter passado o objeto MRE como o parâmetro de estado do usuário do método 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();
}
}
}
Por que não usar wc.DownloadFile vez de wc.DownloadFileAsync se quiser bloquear qualquer maneira ..