在Blazor中,通过IAsyncDisposable接口释放托管资源的一般套路(异步方式)

26 阅读1分钟
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace BlazorAppJavaScript.Components.Pages
{
    public partial class CounterAsync : IAsyncDisposable
    {
        private CancellationTokenSource? _cts;
        private bool _disposed = false;

        // 文件下载方法,支持取消
        private async Task DownloadFileAsync(string url)
        {
            _cts = new CancellationTokenSource();
            try
            {
                using var httpClient = new HttpClient();
                var response = await httpClient.GetAsync(url, _cts.Token);
                response.EnsureSuccessStatusCode();
                var content = await response.Content.ReadAsByteArrayAsync(_cts.Token);
                // 处理下载内容
            }
            catch (OperationCanceledException)
            {
                // 下载被取消
            }
        }

        // 页面关闭时取消下载
        protected virtual async ValueTask DisposeAsyncCore()
        {
            if (_cts != null)
            {
                _cts.Cancel();
                _cts.Dispose();
                _cts = null;
            }
            await Task.CompletedTask;
        }

        public async ValueTask DisposeAsync()
        {
            if (!_disposed)
            {
                await DisposeAsyncCore();
                _disposed = true;
                GC.SuppressFinalize(this);
            }
        }
    }
}

/*ValueTask 和 Task 都用于表示异步操作,但它们有以下主要区别:
1. 内存分配
•	Task:每次异步方法返回 Task 时,都会分配一个对象(即使结果已完成)。
•	ValueTask:是一个结构体(struct),可以避免不必要的堆分配,尤其是在结果已完成或同步可用时。
2. 使用场景
•	Task:适用于大多数异步场景,推荐作为标准返回类型。
•	ValueTask:适合高性能场景,比如结果经常是同步完成的(如缓存命中),可以减少对象分配。
3. 多次等待
•	Task:可以多次 await 或注册回调。
•	ValueTask:只能 await 一次,不能多次等待或注册多个回调,否则行为未定义。
4. API 兼容性
•	Task:与大多数异步 API 兼容。
•	ValueTask:部分 API 不支持,使用时需注意兼容性。
 public async Task<int> GetValueAsync() { ... }      // 标准用法
public async ValueTask<int> GetValueAsync() { ... } // 高性能场景
 */