You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Polly重试不生效且无日志输出,求代码问题排查指导

Troubleshooting Your Connection Wait Logic & Polly Retry Issues

Let's break down what's going wrong with both your original code and the Polly implementation, then fix them step by step.

Why the Original Code Causes Lag

Your initial implementation holds the Monitor lock while sleeping in the while loop. Since Thread.Sleep(100) doesn't release the lock, any other thread trying to acquire _syncRoot will be blocked for the entire duration of the wait. This is exactly what's causing your卡顿 (lag).

Why the Polly Version Isn't Working

Your Polly code has three critical issues:

  1. Incorrect Logging: Your log statement Log.LogInformation("retry {TimeOut}s"); doesn't pass the actual timeout value to the placeholder. It'll just print "retry {TimeOut}s" instead of the real number.
  2. Wrong Callback Signature: For result-based policies (HandleResult<bool>), the retry callback receives a DelegateResult<bool> (not an Exception) as the first parameter. Your code uses (ex, time) which is meant for exception-handling policies.
  3. No Actual Connection Attempt: You're executing () => connection.IsConnected which only checks the current state—you aren't triggering any logic to establish a connection. If connection doesn't auto-reconnect in the background, Polly will just keep checking false forever.
  4. Still Holding the Lock During Retries: Just like the original code, you're running the entire Polly retry sequence inside the Monitor lock. This keeps blocking other threads, so the lag issue remains.

Fixed Implementations

If your connection object has an explicit Connect() method to initiate a connection, use this approach. We'll shrink the lock scope to only protect the initial connection trigger, not the entire wait/retry process:

private bool TryConnect()
{
    // Early exit if already connected
    if (connection.IsConnected)
    {
        return true;
    }

    Monitor.Enter(_syncRoot);
    try
    {
        // Double-check to avoid redundant work (another thread might have connected while we waited for the lock)
        if (connection.IsConnected)
        {
            return true;
        }

        // Define Polly retry policy: retry on failed connection attempts
        var retryPolicy = Policy.HandleResult<bool>(result => !result)
            .WaitAndRetry(
                retryCount: _retryCount,
                sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), // Exponential backoff
                onRetry: (result, timeSpan, retryAttempt, context) =>
                {
                    Log.LogInformation("Connection failed. Retrying in {WaitTime:F1}s (attempt {RetryNumber})", 
                        timeSpan.TotalSeconds, retryAttempt);
                });

        // Execute the actual connection logic
        bool isConnected = retryPolicy.Execute(() =>
        {
            try
            {
                connection.Connect(); // Replace with your actual connection method
                return connection.IsConnected;
            }
            catch (Exception ex)
            {
                Log.LogError(ex, "Connection attempt threw an exception");
                return false;
            }
        });

        return isConnected;
    }
    finally
    {
        Monitor.Exit(_syncRoot);
    }
}

Option 2: Waiting for Auto-Reconnecting Connection

If your connection automatically tries to reconnect in the background (no need to call Connect()), use this approach to wait for the state change outside the lock to avoid blocking other threads:

private async Task<bool> TryConnectAsync()
{
    if (connection.IsConnected)
    {
        return true;
    }

    // Only lock to ensure we don't trigger redundant init logic (if needed)
    Monitor.Enter(_syncRoot);
    try
    {
        if (connection.IsConnected)
        {
            return true;
        }
        // Uncomment if you need to trigger the initial connection attempt
        // connection.InitiateReconnect();
    }
    finally
    {
        Monitor.Exit(_syncRoot);
    }

    // Wait for connection outside the lock to avoid blocking other threads
    int attempt = 0;
    while (!connection.IsConnected && attempt < _retryCount)
    {
        var waitTime = TimeSpan.FromSeconds(Math.Pow(2, attempt));
        await Task.Delay(waitTime);
        Log.LogInformation("Waiting for connection... Attempt {AttemptNumber}", attempt + 1);
        attempt++;
    }

    return connection.IsConnected;
}

内容的提问来源于stack exchange,提问作者finn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 17:57:51