仅在 Windows 关闭时阻止并发线程



我有代码

private void AbrirConexao(string strConexao)
{
try
{
conexao = new NpgsqlConnection(strConexao);
conexao.Open();
}
catch (Exception)
{
ReconectarDB(null, strConexao);
}
}
public bool ReconectarDB(string strConexao)
{
bool erroConexao = false;
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (obj, ea) =>
{
int erro = 0;
while (erro <= 4)
{
Thread.Sleep(1000);
try
{
conexao = new NpgsqlConnection(strConexao);
conexao.Open();
erroConexao = false;
break;
}
catch
{
erro++;
erroConexao = true;
}
}
};
bw.RunWorkerCompleted += (obj, ea) =>
{
if (erroConexao)
DialogReconectando.AlterarTela(ErroConexao.SemConexao);
else
DialogReconectando.Close();
};
bw.RunWorkerAsync();
Application.Current.Dispatcher.Invoke(new Action(() =>
{
if (DialogReconectando == null || Conexao.DialogReconectando.IsLoaded == false)
DialogReconectando = new   DialogErroConexao(ErroConexao.Reconectando);
if(DialogReconectando.ShowActivated)
{
DialogReconectando.ShowActivated = true;
DialogReconectando.ShowDialog();
}
}));
return erroConexao;
}

我正在使用打开连接方法连接到数据库。 当连接失败时,ReconnectDB 正在尝试重新连接数据库。如果失败,将打开一个窗口,其中有两个按钮,重试和中止系统。

问题是在某些情况下,我使用其他并发线程对数据库发出请求。在这些情况下,我不希望它显示新窗口。因此,如果打开了一个窗口,我希望线程锁定,直到窗口关闭。我试图使用EventWaitHandle来解决这个问题。但是,Window也陷入了这种情况。你知道如何解决这个问题吗?

这取决于您希望第二个线程执行的操作。如果希望第二个线程只是跳过显示窗口,则可以使用信号量来确保只有一个线程显示窗口,如下所示:

SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);
private void ShowWindowNonBlocking()
{
bool acquiredLock = false;
try
{
acquiredLock = semaphore.Wait(0);
if (acquiredLock)
{
// This thread now has exclusive access to the isWindowShown variable
var result = MessageBox.Show(
"Retry the connection?",
"Connection Failed",
MessageBoxButtons.RetryCancel);
if (result == DialogResult.Retry)
{
// Retry the connection
}
}
else
{
// Another thread is showing the window
}
}
finally
{
if (acquiredLock)
{
semaphore.Release();
}
}
}

这里有一个很好的网站,我不时参考锁定机制:http://www.albahari.com/threading/part2.aspx#_Semaphore

但是,如果您希望第二个线程阻塞,直到第一个窗口完成(例如,如果您想知道窗口的结果是什么,以便知道是否在第二个线程上重试(,则可以使用锁,如下所示:

private object windowLock = new object();
private void ShowWindowBlocking()
{
lock (windowLock)
{
var result = MessageBox.Show(
"Retry the connection?",
"Connection Failed",
MessageBoxButtons.RetryCancel);
if (result == DialogResult.Retry)
{
// Retry the connection
}
}
}

如果您需要进一步澄清,请告诉我,我将尝试扩展答案。

最新更新