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

C#中Task.Delay误用与任务执行顺序错误导致第二个任务未触发

Fixing Your Timer Task Execution Issues

Let's break down the problems in your current code and fix them step by step:

Root Causes of the Issues

  • Sequential await blocks the second task: Your StartOperations method uses await StartAccessTokenTimer() first, but since StartAccessTokenTimer runs an infinite loop, it never completes—so StartItemsTimer never gets started at all. That's why GetItems is never triggered.
  • Reversed delay durations: You set a 3-second delay in StartAccessTokenTimer (should be 60 seconds) and a 60-second delay in StartItemsTimer (should be 3 seconds).
  • No waiting for initial access token: StartItemsTimer would start with an empty accessToken if it ran, which would likely cause issues with GetItems.

Corrected Implementation

Here's the fixed code with proper parallel task execution, correct delays, and initial token waiting:

private string accessToken = "";
private CancellationTokenSource _cts;

private async Task StartAccessTokenTimer(CancellationToken token)
{
    // Get the first token immediately before starting the loop
    accessToken = await GetAccessToken();
    
    while (!token.IsCancellationRequested)
    {
        // Wait 60 seconds before refreshing the token
        await Task.Delay(TimeSpan.FromSeconds(60), token);
        if (!token.IsCancellationRequested)
        {
            accessToken = await GetAccessToken();
        }
    }
}

private async Task StartItemsTimer(CancellationToken token)
{
    // Wait until we have a valid access token before starting the loop
    while (string.IsNullOrEmpty(accessToken) && !token.IsCancellationRequested)
    {
        await Task.Delay(100, token); // Short poll to check for token
    }
    
    while (!token.IsCancellationRequested)
    {
        if (!string.IsNullOrEmpty(accessToken))
        {
            var items = await GetItems(accessToken, "1");
        }
        // Wait 3 seconds before the next fetch
        await Task.Delay(TimeSpan.FromSeconds(3), token);
    }
}

public async Task StartOperations()
{
    // Create a shared cancellation token source to stop both tasks if needed
    _cts = new CancellationTokenSource();
    var token = _cts.Token;
    
    // Start both tasks in parallel instead of sequentially
    var tokenTask = StartAccessTokenTimer(token);
    var itemsTask = StartItemsTimer(token);
    
    // Wait for both tasks to complete (they'll run until cancelled)
    await Task.WhenAll(tokenTask, itemsTask);
}

// Optional: Method to stop all running tasks cleanly
public void StopOperations()
{
    _cts?.Cancel();
    _cts?.Dispose();
}

Key Improvements Explained

  • Parallel task execution: Instead of awaiting one task before starting the other, we start both tasks at the same time and use Task.WhenAll to wait for both. This ensures neither task blocks the other.
  • Correct delay times: StartAccessTokenTimer now waits 60 seconds between token refreshes, and StartItemsTimer waits 3 seconds between GetItems calls.
  • Initial token waiting: StartItemsTimer waits until accessToken is populated before making any GetItems calls, avoiding invalid token issues.
  • Shared cancellation token: Using a single CancellationTokenSource lets you stop both tasks cleanly when needed, preventing orphaned tasks and resource leaks.
  • Null/empty token check: Added checks to ensure we don't call GetItems with an invalid token.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:58:37