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
awaitblocks the second task: YourStartOperationsmethod usesawait StartAccessTokenTimer()first, but sinceStartAccessTokenTimerruns an infinite loop, it never completes—soStartItemsTimernever gets started at all. That's whyGetItemsis never triggered. - Reversed delay durations: You set a 3-second delay in
StartAccessTokenTimer(should be 60 seconds) and a 60-second delay inStartItemsTimer(should be 3 seconds). - No waiting for initial access token:
StartItemsTimerwould start with an emptyaccessTokenif it ran, which would likely cause issues withGetItems.
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.WhenAllto wait for both. This ensures neither task blocks the other. - Correct delay times:
StartAccessTokenTimernow waits 60 seconds between token refreshes, andStartItemsTimerwaits 3 seconds betweenGetItemscalls. - Initial token waiting:
StartItemsTimerwaits untilaccessTokenis populated before making anyGetItemscalls, avoiding invalid token issues. - Shared cancellation token: Using a single
CancellationTokenSourcelets 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
GetItemswith an invalid token.
内容的提问来源于stack exchange,提问作者barteloma
相关产品推荐
相关产品推荐

