如何解决不良模式关闭线程追逐(重新)启动线程的问题

发布于 2024-11-03 09:35:00 字数 1803 浏览 0 评论 0原文

奇怪的容错线程模式并及时关闭它们。注意到这种模式在产品中反复出现。

假设您有一个容错进程 - 网络连接 - 还加入 SSL,或 WMI 连接和查询,或数据库连接和查询等。

您的网络客户端连接失败时将等待一段时间(假设 5 分钟),然后然后尝试重新连接。

有时,当这种情况发生时,您可能还想停止网络,这会引入第二个线程,表明它正在停止并执行某些关闭操作。

如果容错进程正在等待,那么很容易通过让它等待另一个线程管理的事件来终止它。

由于 Connect 功能的流程较长/成本高昂,您将如何中途停止它?如何在 Cancel() 调用之后/期间管理 Connect() 中的步骤,目前可以在 Connect 创建过程中调用 Cancel/Cleanup new SslStream 并因此成功完成 Connect 并处于不完整状态 - 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 中的每个操作之后继续检查事件然后调用 Cleanup 似乎很难看。

Curious pattern of fault tollerent threads and shutting them down in a timely manner. Noticing this pattern recurring through a product a fair bit.

Say you have a fault tolerant process - a network connection - throw in SSL aswell, or a WMI connection and query, or a database connection and query etc.

Your network client connection when it fails will wait a moment (lets say 5 minutes) and then try and re connect.

Now sometimes while this is happening you may also want to stop the networking, this brings in a second thread signaling that it is stopping and performing some shutdown.

If the the fault tolerant process is waiting then it's easy enough to kill off by having it wait on an event managed by the other thread.

How would you stop the Connect function midway through because it has long/costly processes? How to manage steps in Connect() after/during a Cancel() call, it's possible at the moment to call Cancel/Cleanup while Connect is in the process of creating the new SslStream and thus successfuly finish Connect with an incomplete state - m_network set to the new object.

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(); });
}

Making Connect lock or using a local network variable defeats the purpose of trying to kill it off early.

It seems ugly to keep checking the event after each action in the Connect and then calling Cleanup.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

山川志 2024-11-10 09:35:00

F# 中的异步块或 C# 的异步 CTP 的好处是——您可以外部化取消和超时流程的处理。如果必须的话,您可以使用 TPL 和延续执行类似的操作。

Nice thing about async block in F# or async CTP for C# is -- you can externalize handling of cancellation and timeout flows. You can do similar things with TPL and continuations, if you must.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文