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

WebClient下载等待与取消的通用实现方案技术问询

Alright, let's break down a solid, reusable pattern that fits all your requirements perfectly. Here's how to implement a WebClient download that waits for completion, checks an unmodifiable cancellation flag periodically, and sticks to your async/await constraints:

WebClient Generic Wait & Cancellable Download Pattern

Core Implementation

First, let's assume this is the unmodifiable cancellation flag class you're working with (we can only read its boolean property):

// Unmodifiable flag class (as per your constraints)
public sealed class CancellationFlag
{
    public bool ShouldCancel { get; } // Read-only, no way to modify this class from our code
}

Now here's the download manager that handles the waiting, flag checks, and cancellation logic:

using System;
using System.Net;
using System.Threading;
using System.Threading.Tasks;

public class DownloadManager
{
    public void Download(string downloadUrl, string saveFilePath, CancellationFlag cancellationFlag)
    {
        // Wrap async logic in Task.Run (permitted by your constraints)
        var downloadTask = Task.Run(async () =>
        {
            using var webClient = new WebClient();
            using var cancellationSource = new CancellationTokenSource();

            // Spin up a background task to periodically check the unmodifiable flag
            var flagCheckTask = Task.Run(async () =>
            {
                while (!cancellationSource.Token.IsCancellationRequested)
                {
                    await Task.Delay(150); // Adjust interval based on responsiveness needs (100-500ms works well)
                    if (cancellationFlag.ShouldCancel)
                    {
                        cancellationSource.Cancel();
                        break;
                    }
                }
            });

            try
            {
                // Execute the download with cancellation support
                await webClient.DownloadFileTaskAsync(new Uri(downloadUrl), saveFilePath, cancellationSource.Token);
                Console.WriteLine("Download completed successfully!");
            }
            catch (OperationCanceledException)
            {
                // Clean up partial downloads if cancellation triggers
                Console.WriteLine("Download cancelled by external flag");
                if (System.IO.File.Exists(saveFilePath))
                {
                    System.IO.File.Delete(saveFilePath);
                }
            }
            catch (Exception ex)
            {
                // Handle other download errors (e.g., network issues)
                Console.WriteLine($"Download failed: {ex.Message}");
            }
            finally
            {
                // Ensure the flag-checking task gets cleaned up
                cancellationSource.Cancel();
                await flagCheckTask;
            }
        });

        // Block the current thread until download completes (meets your "wait before other operations" requirement)
        downloadTask.Wait();
    }
}

Key Details Explained

  • Async/Await Compliance: All asynchronous logic is wrapped in Task.Run(async () => { ... }), with Wait() used to block the main thread until completion—exactly what your constraints allow.
  • Periodic Flag Checks: A background task polls the unmodifiable ShouldCancel property at configurable intervals. When the flag is triggered, it cancels the download via a CancellationTokenSource.
  • Clean Cancellation Handling: If the download is cancelled, we delete any partial files to avoid leaving invalid data behind.
  • Blocking Wait: The outer downloadTask.Wait() ensures your code won't proceed to other operations until the download (or cancellation) is fully finished.

Usage Example

// Get your unmodifiable cancellation flag instance (from your existing code)
var cancellationFlag = new CancellationFlag();

// Simulate an external trigger for cancellation (e.g., user clicking a cancel button)
Task.Run(() =>
{
    Thread.Sleep(6000); // Cancel after 6 seconds
    // Note: In your real code, the ShouldCancel property would be updated by the unmodifiable class's internal logic
});

// Run the download
var manager = new DownloadManager();
manager.Download("https://example.com/large-document.pdf", @"C:\Downloads\my-document.pdf", cancellationFlag);

// This code only runs AFTER the download completes or is cancelled
Console.WriteLine("Download flow finished—proceeding with next operations");

Quick Notes

  • Adjust Polling Interval: Tweak the Task.Delay(150) value to balance responsiveness and CPU usage. Shorter intervals react faster but use more resources.
  • WebClient Alternative: If you can use HttpClient instead, the logic is nearly identical—just replace DownloadFileTaskAsync with streaming the response to a file.
  • Error Handling: Expand the exception block to fit your needs (e.g., retry logic, logging to a file).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:41:19