Любопытная картина неисправности толерантных потоков и своевременного их отключения. Заметив эту закономерность, периодически повторяющуюся через продукт.
Скажем, у вас отказоустойчивый процесс - сетевое соединение - добавьте также SSL, или соединение и запрос WMI, или соединение с базой данных и запрос и т. Д.
Ваше сетевое клиентское соединение в случае сбоя будет ждать некоторое время (скажем, 5 минут), а затем попытаться повторно подключиться.
Теперь иногда, когда это происходит, вы также можете захотеть прекратить работу сети, это приводит ко второму потоку, сигнализирующему о том, что он останавливается и выполняет некоторое отключение.
Если отказоустойчивый процесс ожидает, то достаточно просто убить его, ожидая события, управляемого другим потоком.
Как бы вы остановили функцию Connect на полпути, потому что она имеет длинные / дорогостоящие процессы? Как управлять шагами в Connect()
после / во время вызова Cancel()
, в данный момент возможно вызвать Отмена / Очистить, когда Connect находится в процессе создания нового SslStream и, таким образом, успешно завершить соединение с неполным состоянием - набор m_network на новый объект.
private TcpClient m_network = new TcpClient();
private ManualResetEvent m_closing = new ManualResetEvent(true);
private void Connect()
{
try
{
m_network.Connect(m_config.Address.Host, m_config.Address.Port);
SslStream sslStream = new SslStream(m_network.GetStream(), true, ValidateServerCertificate, ClientCertificateSelection );
X509CertificateCollection clientCertificates = GetClientCertificates();
sslStream.AuthenticateAsClient(m_config.Address.Host, clientCertificates, SslProtocols.Default, false );
// do more stuff in a new thread
}
catch (System.Exception ex)
{ Reset(); }
}
public void BeginExecution()
{
ThreadPool.QueueUserWorkItem(delegate
{
m_closing.Reset();
Connect();
});
}
public void Cancel()
{
m_closing.Set();
Cleanup();
}
private void Cleanup()
{
TcpClient tempClient = m_network;
m_network = new TcpClient();
if (tempClient.Connected)
{
tempClient.Close();
}
}
void Reset(){
if (m_closing.WaitOne(0))
return;
Cleanup();
if (m_closing.WaitOne(TimeSpan.FromSeconds(300)))
return;
ThreadPool.QueueUserWorkItem(delegate { Connect(); });
}
Установление блокировки Connect или использование локальной сетевой переменной отрицательно сказывается на попытке убить его раньше.
Кажется уродливым продолжать проверять событие после каждого действия в Connect и затем вызывать очистку.