C#异步编程陷阱:从死锁规避到性能优化的完整指南

本文针对C#异步编程在实际开发中的核心痛点问题,通过构建真实的高并发场景,深度分析死锁产生条件、async/await误用、资源泄漏、性能瓶颈等高频问题。提供从基础用法到高级优化的完整解决方案,涵盖任务并行库、ValueTask优化、取消令牌等实战技术。

图片[1]-C#异步编程陷阱:从死锁规避到性能优化的完整指南

一、异步死锁问题与解决方案

1. 同步上下文导致的死锁

理解WinForms、WPF等UI线程环境中的死锁机制:

// 死锁问题重现与分析
public class AsyncDeadlockDemo
{
    // 危险的异步方法 - 在UI线程中调用会导致死锁
    public async Task<string> DangerousGetDataAsync()
    {
        // 模拟异步操作
        await Task.Delay(1000).ConfigureAwait(false);
        
        // 这里会尝试回到原始同步上下文(UI线程)
        // 但如果UI线程正在同步等待这个方法,就会死锁
        return "数据结果";
    }
    
    // 死锁场景演示
    public void DemonstrateDeadlock()
    {
        // 在UI线程中同步等待异步方法 - 经典死锁模式
        var result = DangerousGetDataAsync().Result;
        Console.WriteLine(result);
    }
    
    // 解决方案1: 全异步化
    public async Task SafeApproach1Async()
    {
        var result = await DangerousGetDataAsync();
        Console.WriteLine(result);
    }
    
    // 解决方案2: 使用ConfigureAwait(false)
    public async Task<string> SafeGetDataAsync()
    {
        await Task.Delay(1000).ConfigureAwait(false);
        return "安全的数据结果";
    }
    
    // 解决方案3: 使用Task.Run脱离同步上下文
    public async Task<string> ThreadSafeGetDataAsync()
    {
        return await Task.Run(async () =>
        {
            await Task.Delay(1000);
            return "线程安全的数据";
        });
    }
}

// 死锁检测工具
public class DeadlockDetector
{
    private readonly object _lockObject = new object();
    private readonly HashSet<Task> _pendingTasks = new HashSet<Task>();
    private readonly Timer _deadlockTimer;
    
    public DeadlockDetector()
    {
        // 每5秒检查一次可能的死锁
        _deadlockTimer = new Timer(CheckForDeadlocks, null, 5000, 5000);
    }
    
    public Task TrackTask(Task task)
    {
        lock (_lockObject)
        {
            _pendingTasks.Add(task);
        }
        
        task.ContinueWith(t =>
        {
            lock (_lockObject)
            {
                _pendingTasks.Remove(t);
            }
        }, TaskContinuationOptions.ExecuteSynchronously);
        
        return task;
    }
    
    private void CheckForDeadlocks(object state)
    {
        lock (_lockObject)
        {
            var now = DateTime.Now;
            var deadlockedTasks = _pendingTasks
                .Where(t => t.Status == TaskStatus.WaitingForActivation ||
                           t.Status == TaskStatus.WaitingToRun ||
                           t.Status == TaskStatus.Running)
                .Where(t => (now - t.CreationTime).TotalSeconds > 30) // 超过30秒认为可能死锁
                .ToList();
                
            if (deadlockedTasks.Any())
            {
                Console.WriteLine($"警告: 检测到 {deadlockedTasks.Count} 个可能死锁的任务");
                foreach (var task in deadlockedTasks)
                {
                    Console.WriteLine($"任务状态: {task.Status}, 创建时间: {task.CreationTime}");
                }
            }
        }
    }
}

2. 异步方法中的锁竞争问题

理解异步环境下的锁机制陷阱:

// 异步锁竞争问题与解决方案
public class AsyncLockCompetition
{
    // 问题代码:在异步方法中使用lock
    private readonly object _syncLock = new object();
    private int _sharedResource = 0;
    
    public async Task<int> ProblematicIncrementAsync()
    {
        // 这会导致线程阻塞,违背异步初衷
        lock (_syncLock)
        {
            // 在锁内执行异步操作 - 错误!
            var result = await SomeAsyncOperation();
            _sharedResource += result;
            return _sharedResource;
        }
    }
    
    // 解决方案1: 使用SemaphoreSlim
    private readonly SemaphoreSlim _asyncLock = new SemaphoreSlim(1, 1);
    
    public async Task<int> SafeIncrementAsync()
    {
        await _asyncLock.WaitAsync();
        try
        {
            var result = await SomeAsyncOperation();
            _sharedResource += result;
            return _sharedResource;
        }
        finally
        {
            _asyncLock.Release();
        }
    }
    
    // 解决方案2: 使用AsyncLock封装
    public class AsyncLock : IDisposable
    {
        private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
        private readonly Task<IDisposable> _releaser;
        
        public AsyncLock()
        {
            _releaser = Task.FromResult((IDisposable)new Releaser(this));
        }
        
        public Task<IDisposable> LockAsync()
        {
            var wait = _semaphore.WaitAsync();
            return wait.IsCompleted ?
                _releaser :
                wait.ContinueWith((_, state) => (IDisposable)state!,
                    _releaser.Result, CancellationToken.None,
                    TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
        }
        
        private void Release()
        {
            _semaphore.Release();
        }
        
        private class Releaser : IDisposable
        {
            private readonly AsyncLock _lock;
            
            public Releaser(AsyncLock @lock)
            {
                _lock = @lock;
            }
            
            public void Dispose()
            {
                _lock.Release();
            }
        }
        
        public void Dispose()
        {
            _semaphore.Dispose();
        }
    }
    
    // 使用AsyncLock的示例
    private readonly AsyncLock _advancedLock = new AsyncLock();
    
    public async Task<int> AdvancedIncrementAsync()
    {
        using (await _advancedLock.LockAsync())
        {
            var result = await SomeAsyncOperation();
            _sharedResource += result;
            return _sharedResource;
        }
    }
    
    private async Task<int> SomeAsyncOperation()
    {
        await Task.Delay(100);
        return 1;
    }
}

// 异步并发控制工具
public class AsyncConcurrencyController
{
    private readonly LimitedConcurrencyLevelTaskScheduler _scheduler;
    private readonly TaskFactory _taskFactory;
    
    public AsyncConcurrencyController(int maxDegreeOfParallelism)
    {
        _scheduler = new LimitedConcurrencyLevelTaskScheduler(maxDegreeOfParallelism);
        _taskFactory = new TaskFactory(_scheduler);
    }
    
    public Task<T> RunWithConcurrencyControl<T>(Func<Task<T>> function)
    {
        return _taskFactory.StartNew(function).Unwrap();
    }
    
    // 自定义任务调度器
    private class LimitedConcurrencyLevelTaskScheduler : TaskScheduler
    {
        [ThreadStatic]
        private static bool _currentThreadIsProcessingItems;
        
        private readonly LinkedList<Task> _tasks = new LinkedList<Task>();
        private readonly int _maxDegreeOfParallelism;
        private int _delegatesQueuedOrRunning = 0;
        
        public LimitedConcurrencyLevelTaskScheduler(int maxDegreeOfParallelism)
        {
            _maxDegreeOfParallelism = maxDegreeOfParallelism > 0 ? maxDegreeOfParallelism : Environment.ProcessorCount;
        }
        
        protected override IEnumerable<Task> GetScheduledTasks()
        {
            lock (_tasks)
            {
                return _tasks.ToArray();
            }
        }
        
        protected override void QueueTask(Task task)
        {
            lock (_tasks)
            {
                _tasks.AddLast(task);
                
                if (_delegatesQueuedOrRunning < _maxDegreeOfParallelism)
                {
                    ++_delegatesQueuedOrRunning;
                    NotifyThreadPoolOfPendingWork();
                }
            }
        }
        
        protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
        {
            if (!_currentThreadIsProcessingItems) return false;
            
            if (taskWasPreviouslyQueued)
            {
                if (TryDequeue(task))
                {
                    return TryExecuteTask(task);
                }
                return false;
            }
            
            return TryExecuteTask(task);
        }
        
        private void NotifyThreadPoolOfPendingWork()
        {
            ThreadPool.UnsafeQueueUserWorkItem(_ =>
            {
                _currentThreadIsProcessingItems = true;
                try
                {
                    while (true)
                    {
                        Task item;
                        lock (_tasks)
                        {
                            if (_tasks.Count == 0)
                            {
                                --_delegatesQueuedOrRunning;
                                break;
                            }
                            
                            item = _tasks.First!.Value;
                            _tasks.RemoveFirst();
                        }
                        
                        TryExecuteTask(item);
                    }
                }
                finally
                {
                    _currentThreadIsProcessingItems = false;
                }
            }, null);
        }
        
        protected override bool TryDequeue(Task task)
        {
            lock (_tasks)
            {
                return _tasks.Remove(task);
            }
        }
    }
}

二、异步资源管理与性能优化

1. IAsyncDisposable与资源清理

正确处理异步资源的生命周期:

// 异步资源管理最佳实践
public class AsyncResourceManagement
{
    // 实现IAsyncDisposable的示例类
    public class AsyncDatabaseConnection : IAsyncDisposable, IDisposable
    {
        private bool _disposed = false;
        private readonly SemaphoreSlim _connectionLock = new SemaphoreSlim(1, 1);
        private HttpClient? _httpClient;
        
        public AsyncDatabaseConnection(string connectionString)
        {
            _httpClient = new HttpClient();
            Console.WriteLine("数据库连接已创建");
        }
        
        public async Task<string> QueryAsync(string sql)
        {
            if (_disposed)
                throw new ObjectDisposedException(nameof(AsyncDatabaseConnection));
                
            await _connectionLock.WaitAsync();
            try
            {
                // 模拟数据库查询
                await Task.Delay(100);
                return $"查询结果: {sql}";
            }
            finally
            {
                _connectionLock.Release();
            }
        }
        
        // 异步释放
        public async ValueTask DisposeAsync()
        {
            await DisposeAsyncCore();
            Dispose(false);
            GC.SuppressFinalize(this);
        }
        
        protected virtual async ValueTask DisposeAsyncCore()
        {
            if (!_disposed)
            {
                if (_httpClient != null)
                {
                    _httpClient.Dispose();
                    _httpClient = null;
                }
                
                // 模拟异步清理
                await Task.Delay(50);
                Console.WriteLine("数据库连接已异步关闭");
                
                _disposed = true;
            }
        }
        
        // 同步释放
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        
        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    _httpClient?.Dispose();
                    _connectionLock.Dispose();
                }
                
                _disposed = true;
            }
        }
        
        ~AsyncDatabaseConnection()
        {
            Dispose(false);
        }
    }
    
    // 使用using await的示例
    public static async Task DemonstrateAsyncUsing()
    {
        await using var connection = new AsyncDatabaseConnection("Server=...");
        var result = await connection.QueryAsync("SELECT * FROM Users");
        Console.WriteLine(result);
        
        // 离开作用域时自动调用DisposeAsync
    }
    
    // 批量异步资源管理
    public class AsyncResourcePool<T> : IAsyncDisposable where T : IAsyncDisposable
    {
        private readonly ConcurrentBag<T> _resources = new ConcurrentBag<T>();
        private readonly Func<Task<T>> _factory;
        private readonly int _maxSize;
        private int _currentCount = 0;
        private bool _disposed = false;
        
        public AsyncResourcePool(Func<Task<T>> factory, int maxSize = 10)
        {
            _factory = factory;
            _maxSize = maxSize;
        }
        
        public async Task<T> GetAsync()
        {
            if (_disposed)
                throw new ObjectDisposedException(nameof(AsyncResourcePool<T>));
                
            if (_resources.TryTake(out var resource))
            {
                return resource;
            }
            
            if (_currentCount < _maxSize)
            {
                Interlocked.Increment(ref _currentCount);
                return await _factory();
            }
            
            // 等待资源可用
            var tcs = new TaskCompletionSource<T>();
            // 简化实现,实际中需要更复杂的等待逻辑
            await Task.Delay(100);
            return await _factory();
        }
        
        public void Return(T resource)
        {
            if (_disposed)
            {
                // 如果池已释放,直接释放资源
                _ = DisposeResourceAsync(resource);
                return;
            }
            
            _resources.Add(resource);
        }
        
        public async ValueTask DisposeAsync()
        {
            if (_disposed) return;
            
            _disposed = true;
            var disposalTasks = new List<Task>();
            
            while (_resources.TryTake(out var resource))
            {
                disposalTasks.Add(DisposeResourceAsync(resource));
            }
            
            await Task.WhenAll(disposalTasks);
        }
        
        private async Task DisposeResourceAsync(T resource)
        {
            try
            {
                await resource.DisposeAsync();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"资源释放失败: {ex.Message}");
            }
        }
    }
}

// 异步Lazy初始化
public class AsyncLazy<T> : Lazy<Task<T>>
{
    public AsyncLazy(Func<Task<T>> taskFactory) 
        : base(() => Task.Run(taskFactory))
    {
    }
    
    public AsyncLazy(Func<T> valueFactory)
        : base(() => Task.Run(valueFactory))
    {
    }
    
    public TaskAwaiter<T> GetAwaiter() => Value.GetAwaiter();
}

// 使用示例
public class AsyncLazyDemo
{
    private readonly AsyncLazy<HttpClient> _lazyHttpClient = new AsyncLazy<HttpClient>(() =>
    {
        var client = new HttpClient();
        // 模拟耗时的初始化
        return Task.FromResult(client);
    });
    
    public async Task<string> GetDataAsync()
    {
        var client = await _lazyHttpClient;
        return await client.GetStringAsync("https://api.example.com/data");
    }
}

2. ValueTask性能优化

在热点路径中使用ValueTask减少内存分配:

// ValueTask性能优化实战
public class ValueTaskOptimization
{
    // 传统Task方式 - 每次调用都会分配Task对象
    public async Task<int> TraditionalAsyncMethod(int input)
    {
        if (input < 0)
        {
            throw new ArgumentException("输入不能为负数");
        }
        
        if (input == 0)
        {
            return 0; // 同步完成,但仍然分配Task
        }
        
        await Task.Delay(100); // 异步操作
        return input * 2;
    }
    
    // 优化后的ValueTask方式
    public async ValueTask<int> OptimizedAsyncMethod(int input)
    {
        if (input < 0)
        {
            throw new ArgumentException("输入不能为负数");
        }
        
        // 同步快速路径 - 不分配Task
        if (input == 0)
        {
            return 0;
        }
        
        // 异步路径
        await Task.Delay(100);
        return input * 2;
    }
    
    // 缓存常用结果的ValueTask
    public class CachedValueTaskProvider
    {
        private readonly ConcurrentDictionary<int, ValueTask<int>> _cache = new();
        
        public ValueTask<int> GetValueAsync(int key)
        {
            if (_cache.TryGetValue(key, out var cachedTask))
            {
                return cachedTask;
            }
            
            // 创建新的ValueTask
            var valueTask = ComputeValueAsync(key);
            _cache.TryAdd(key, valueTask);
            return valueTask;
        }
        
        private async ValueTask<int> ComputeValueAsync(int key)
        {
            // 模拟计算
            await Task.Delay(50);
            return key * key;
        }
    }
    
    // IValueTaskSource自定义实现(高级用法)
    public class CustomValueTaskSource<T> : IValueTaskSource<T>
    {
        private T? _result;
        private Exception? _exception;
        private ManualResetValueTaskSourceCore<T> _core;
        
        public ValueTask<T> Task => new ValueTask<T>(this, _core.Version);
        
        public void SetResult(T result)
        {
            _result = result;
            _core.SetResult(result);
        }
        
        public void SetException(Exception exception)
        {
            _exception = exception;
            _core.SetException(exception);
        }
        
        public T GetResult(short token)
        {
            return _core.GetResult(token);
        }
        
        public ValueTaskSourceStatus GetStatus(short token)
        {
            return _core.GetStatus(token);
        }
        
        public void OnCompleted(Action<object?> continuation, object? state, short token, ValueTaskSourceOnCompletedFlags flags)
        {
            _core.OnCompleted(continuation, state, token, flags);
        }
    }
}

// 异步枚举器性能优化
public class AsyncEnumerableOptimization
{
    // 传统的异步枚举器
    public static async IAsyncEnumerable<int> TraditionalAsyncSequence()
    {
        for (int i = 0; i < 100; i++)
        {
            await Task.Delay(10);
            yield return i;
        }
    }
    
    // 使用池化减少内存分配
    public static async IAsyncEnumerable<int> OptimizedAsyncSequence()
    {
        // 使用ArrayPool减少数组分配
        var buffer = ArrayPool<int>.Shared.Rent(10);
        try
        {
            for (int i = 0; i < 100; i += 10)
            {
                await Task.Delay(10);
                
                // 批量处理
                for (int j = 0; j < 10 && i + j < 100; j++)
                {
                    buffer[j] = i + j;
                }
                
                for (int j = 0; j < 10 && i + j < 100; j++)
                {
                    yield return buffer[j];
                }
            }
        }
        finally
        {
            ArrayPool<int>.Shared.Return(buffer);
        }
    }
    
    // 配置枚举器取消和并发
    public static async IAsyncEnumerable<int> ConfiguredAsyncSequence(
        [EnumeratorCancellation] CancellationToken cancellationToken = default)
    {
        var options = new System.Threading.Channels.BoundedChannelOptions(10)
        {
            FullMode = System.Threading.Channels.BoundedChannelFullMode.Wait,
            SingleReader = true,
            SingleWriter = true
        };
        
        var channel = System.Threading.Channels.Channel.CreateBounded<int>(options);
        
        // 生产者任务
        _ = Task.Run(async () =>
        {
            try
            {
                for (int i = 0; i < 100; i++)
                {
                    if (cancellationToken.IsCancellationRequested)
                        break;
                        
                    await channel.Writer.WriteAsync(i, cancellationToken);
                    await Task.Delay(10, cancellationToken);
                }
            }
            finally
            {
                channel.Writer.Complete();
            }
        }, cancellationToken);
        
        // 消费者
        await foreach (var item in channel.Reader.ReadAllAsync(cancellationToken))
        {
            yield return item;
        }
    }
}

三、取消令牌与超时控制

1. 取消令牌的最佳实践

正确使用CancellationToken处理取消请求:

// 取消令牌完整解决方案
public class CancellationTokenBestPractices
{
    // 基础取消令牌使用
    public async Task<string> ProcessWithCancellationAsync(
        string data, 
        CancellationToken cancellationToken = default)
    {
        // 在方法开始时检查取消请求
        cancellationToken.ThrowIfCancellationRequested();
        
        try
        {
            // 模拟工作
            for (int i = 0; i < 100; i++)
            {
                cancellationToken.ThrowIfCancellationRequested();
                
                // 将取消令牌传递给所有异步操作
                await Task.Delay(10, cancellationToken);
                
                // 模拟CPU工作
                SimulateCpuWork(i);
            }
            
            return $"处理完成: {data}";
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("操作被取消");
            throw;
        }
    }
    
    // 链接多个取消令牌
    public async Task<string> ProcessWithLinkedTokensAsync(
        string data,
        TimeSpan timeout,
        CancellationToken externalToken = default)
    {
        using var timeoutCts = new CancellationTokenSource(timeout);
        using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(
            externalToken, timeoutCts.Token);
            
        try
        {
            return await ProcessWithCancellationAsync(data, linkedCts.Token);
        }
        catch (OperationCanceledException ex) when (timeoutCts.Token.IsCancellationRequested)
        {
            throw new TimeoutException("操作超时", ex);
        }
    }
    
    // 取消令牌注册回调
    public async Task<string> ProcessWithCallbacksAsync(
        string data,
        CancellationToken cancellationToken = default)
    {
        // 注册取消回调
        using var registration = cancellationToken.Register(() =>
        {
            Console.WriteLine("取消请求已收到,正在清理资源...");
            CleanupResources();
        });
        
        try
        {
            return await ProcessWithCancellationAsync(data, cancellationToken);
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("操作已取消完成");
            throw;
        }
    }
    
    // 自定义取消令牌源
    public class ThrottlingCancellationTokenSource : CancellationTokenSource
    {
        private readonly TimeSpan _throttlePeriod;
        private DateTime _lastCancellation = DateTime.MinValue;
        
        public ThrottlingCancellationTokenSource(TimeSpan throttlePeriod)
        {
            _throttlePeriod = throttlePeriod;
        }
        
        public new void Cancel()
        {
            var now = DateTime.UtcNow;
            if (now - _lastCancellation < _throttlePeriod)
            {
                Console.WriteLine("取消请求被限流");
                return;
            }
            
            _lastCancellation = now;
            base.Cancel();
        }
        
        public void Cancel(bool force)
        {
            if (force)
            {
                _lastCancellation = DateTime.MinValue;
            }
            Cancel();
        }
    }
    
    private void SimulateCpuWork(int iteration)
    {
        // 模拟CPU密集型工作
        for (int i = 0; i < 1000; i++)
        {
            _ = Math.Sqrt(i);
        }
    }
    
    private void CleanupResources()
    {
        Console.WriteLine("清理临时资源...");
    }
}

// 异步操作超时控制
public class AsyncTimeoutControl
{
    // 使用Task.WhenAny实现超时
    public static async Task<T> WithTimeoutAsync<T>(
        Task<T> task,
        TimeSpan timeout,
        CancellationToken cancellationToken = default)
    {
        using var timeoutCts = new CancellationTokenSource();
        using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(
            cancellationToken, timeoutCts.Token);
            
        var timeoutTask = Task.Delay(timeout, linkedCts.Token);
        var completedTask = await Task.WhenAny(task, timeoutTask);
        
        if (completedTask == timeoutTask)
        {
            throw new TimeoutException($"操作在 {timeout} 后超时");
        }
        
        timeoutCts.Cancel(); // 取消超时任务
        return await task;
    }
    
    // 带默认值的超时控制
    public static async Task<T?> WithTimeoutOrDefaultAsync<T>(
        Task<T> task,
        TimeSpan timeout,
        T? defaultValue = default)
    {
        try
        {
            return await WithTimeoutAsync(task, timeout);
        }
        catch (TimeoutException)
        {
            return defaultValue;
        }
    }
    
    // 可配置的重试与超时策略
    public class RetryWithTimeoutPolicy
    {
        private readonly int _maxRetries;
        private readonly TimeSpan _timeout;
        private readonly TimeSpan _retryDelay;
        
        public RetryWithTimeoutPolicy(int maxRetries, TimeSpan timeout, TimeSpan retryDelay)
        {
            _maxRetries = maxRetries;
            _timeout = timeout;
            _retryDelay = retryDelay;
        }
        
        public async Task<T> ExecuteAsync<T>(Func<CancellationToken, Task<T>> operation)
        {
            var exceptions = new List<Exception>();
            
            for (int attempt = 1; attempt <= _maxRetries; attempt++)
            {
                try
                {
                    using var cts = new CancellationTokenSource(_timeout);
                    return await operation(cts.Token);
                }
                catch (Exception ex) when (ex is TimeoutException or OperationCanceledException)
                {
                    exceptions.Add(ex);
                    
                    if (attempt == _maxRetries)
                    {
                        throw new AggregateException(
                            $"在 {_maxRetries} 次重试后操作仍失败", exceptions);
                    }
                    
                    Console.WriteLine($"第 {attempt} 次尝试失败,{_retryDelay} 后重试...");
                    await Task.Delay(_retryDelay);
                }
            }
            
            throw new InvalidOperationException("不应到达此处");
        }
    }
}

四、异步异常处理与调试

1. 异步异常传播与处理

理解异步方法中的异常行为:

// 异步异常处理完整方案
public class AsyncExceptionHandling
{
    // 异步异常的传播特性
    public async Task DemonstrateExceptionPropagation()
    {
        try
        {
            await FaultyAsyncMethod();
        }
        catch (InvalidOperationException ex)
        {
            Console.WriteLine($"捕获到异常: {ex.Message}");
        }
    }
    
    private async Task FaultyAsyncMethod()
    {
        await Task.Delay(100);
        throw new InvalidOperationException("异步操作失败");
    }
    
    // 多个异步操作的异常处理
    public async Task MultipleAsyncOperationsHandling()
    {
        var tasks = new[]
        {
                Task.Run(() => SometimesFails(1)),
                Task.Run(() => SometimesFails(2)),
                Task.Run(() => SometimesFails(3))
            };
            
        try
        {
            // 等待所有任务完成,收集所有异常
            await Task.WhenAll(tasks);
        }
        catch (AggregateException agEx)
        {
            foreach (var ex in agEx.InnerExceptions)
            {
                Console.WriteLine($"任务异常: {ex.Message}");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"其他异常: {ex.Message}");
        }
    }
    
    // 使用WhenAll但分别处理异常
    public async Task IndividualExceptionHandling()
    {
        var tasks = new[]
        {
                Task.Run(() => SometimesFails(1)),
                Task.Run(() => SometimesFails(2)),
                Task.Run(() => SometimesFails(3))
            };
            
        var completedTasks = new List<Task>();
        
        foreach (var task in tasks)
        {
            try
            {
                await task;
                completedTasks.Add(task);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"任务失败: {ex.Message}");
                // 继续处理其他任务
            }
        }
        
        Console.WriteLine($"成功完成 {completedTasks.Count} 个任务");
    }
    
    private async Task SometimesFails(int id)
    {
        await Task.Delay(100);
        
        if (id % 2 == 0) // 偶数ID失败
        {
            throw new InvalidOperationException($"任务 {id} 故意失败");
        }
        
        Console.WriteLine($"任务 {id} 完成");
    }
    
    // 异步方法中的finally块行为
    public async Task FinallyBlockBehaviorAsync()
    {
        try
        {
            Console.WriteLine("try块开始");
            await Task.Delay(100);
            throw new Exception("测试异常");
        }
        finally
        {
            // 即使异步操作抛出异常,finally块也会执行
            Console.WriteLine("finally块执行");
            await CleanupAsync(); // finally块中也可以使用await
        }
    }
    
    private async Task CleanupAsync()
    {
        await Task.Delay(50);
        Console.WriteLine("清理完成");
    }
    
    // 异步栈追踪增强
    public class AsyncStackTraceHelper
    {
        [System.Runtime.CompilerServices.AsyncMethodBuilder(typeof(AsyncTaskMethodBuilder))]
        public static async Task<T> WithEnhancedStackTrace<T>(Func<Task<T>> taskFactory)
        {
            try
            {
                return await taskFactory();
            }
            catch (Exception ex)
            {
                EnhanceExceptionStackTrace(ex);
                throw;
            }
        }
        
        private static void EnhanceExceptionStackTrace(Exception exception)
        {
            // 在实际应用中,这里可以添加额外的调试信息
            // 或者使用CallerMemberName、CallerFilePath等特性
            Console.WriteLine($"增强异常信息: {exception}");
        }
    }
}

// 异步操作的状态监控
public class AsyncOperationMonitor
{
    private readonly ConcurrentDictionary<string, AsyncOperationInfo> _operations = new();
    
    public async Task<T> MonitorAsync<T>(string operationId, Func<Task<T>> operation)
    {
        var info = new AsyncOperationInfo
        {
            Id = operationId,
            StartTime = DateTime.UtcNow,
            Status = AsyncOperationStatus.Running
        };
        
        _operations[operationId] = info;
        
        try
        {
            var result = await operation();
            info.Status = AsyncOperationStatus.Completed;
            info.EndTime = DateTime.UtcNow;
            return result;
        }
        catch (Exception ex)
        {
            info.Status = AsyncOperationStatus.Faulted;
            info.Error = ex.Message;
            info.EndTime = DateTime.UtcNow;
            throw;
        }
        finally
        {
            // 一段时间后自动清理完成的记录
            _ = Task.Delay(TimeSpan.FromMinutes(5))
                .ContinueWith(_ => _operations.TryRemove(operationId, out _));
        }
    }
    
    public IReadOnlyDictionary<string, AsyncOperationInfo> GetActiveOperations()
    {
        return _operations.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
    }
    
    public class AsyncOperationInfo
    {
        public string Id { get; set; } = string.Empty;
        public DateTime StartTime { get; set; }
        public DateTime? EndTime { get; set; }
        public AsyncOperationStatus Status { get; set; }
        public string? Error { get; set; }
        public TimeSpan Duration => (EndTime ?? DateTime.UtcNow) - StartTime;
    }
    
    public enum AsyncOperationStatus
    {
        Running,
        Completed,
        Faulted,
        Canceled
    }
}

五、生产环境最佳实践

1. 异步代码质量检查清单

// 异步编程最佳实践检查工具
public static class AsyncBestPracticesChecker
{
    public static void AnalyzeMethod(SyntaxTree syntaxTree, SemanticModel semanticModel)
    {
        var root = syntaxTree.GetRoot();
        var asyncMethods = root.DescendantNodes()
            .OfType<MethodDeclarationSyntax>()
            .Where(m => m.Modifiers.Any(SyntaxKind.AsyncKeyword));
            
        foreach (var method in asyncMethods)
        {
            CheckAsyncMethod(method, semanticModel);
        }
    }
    
    private static void CheckAsyncMethod(MethodDeclarationSyntax method, SemanticModel semanticModel)
    {
        var issues = new List<string>();
        
        // 检查1: 异步方法名是否以Async结尾
        if (!method.Identifier.ValueText.EndsWith("Async"))
        {
            issues.Add("异步方法名应以'Async'结尾");
        }
        
        // 检查2: 返回类型是否为Task/Task<T>/ValueTask/ValueTask<T>
        var returnType = method.ReturnType.ToString();
        if (!returnType.StartsWith("Task") && !returnType.StartsWith("ValueTask"))
        {
            issues.Add("异步方法应返回Task或ValueTask");
        }
        
        // 检查3: 是否使用了.Result或.Wait()
        var invocations = method.DescendantNodes().OfType<InvocationExpressionSyntax>();
        foreach (var invocation in invocations)
        {
            var invocationText = invocation.ToString();
            if (invocationText.Contains(".Result") || invocationText.Contains(".Wait("))
            {
                issues.Add("避免在异步方法中使用.Result或.Wait()");
            }
        }
        
        // 检查4: 是否使用了ConfigureAwait(false)
        var awaitExpressions = method.DescendantNodes().OfType<AwaitExpressionSyntax>();
        bool hasConfigureAwait = awaitExpressions.Any(aw => 
            aw.Expression.ToString().Contains("ConfigureAwait(false)"));
            
        if (!hasConfigureAwait && awaitExpressions.Any())
        {
            issues.Add("考虑在非UI代码中使用ConfigureAwait(false)");
        }
        
        if (issues.Any())
        {
            Console.WriteLine($"方法 {method.Identifier.ValueText} 发现问题:");
            foreach (var issue in issues)
            {
                Console.WriteLine($"  - {issue}");
            }
        }
    }
}

// 异步性能计数器
public class AsyncPerformanceCounter
{
    private long _totalOperations;
    private long _failedOperations;
    private long _canceledOperations;
    private readonly Stopwatch _totalTime = new Stopwatch();
    
    public async Task<T> TrackAsync<T>(Func<Task<T>> operation, string operationName = "")
    {
        Interlocked.Increment(ref _totalOperations);
        _totalTime.Start();
        
        try
        {
            return await operation();
        }
        catch (OperationCanceledException)
        {
            Interlocked.Increment(ref _canceledOperations);
            throw;
        }
        catch (Exception)
        {
            Interlocked.Increment(ref _failedOperations);
            throw;
        }
        finally
        {
            _totalTime.Stop();
        }
    }
    
    public AsyncPerformanceStats GetStats()
    {
        return new AsyncPerformanceStats
        {
            TotalOperations = _totalOperations,
            FailedOperations = _failedOperations,
            CanceledOperations = _canceledOperations,
            TotalTime = _totalTime.Elapsed,
            AverageTimePerOperation = _totalOperations > 0 ? 
                _totalTime.Elapsed / _totalOperations : TimeSpan.Zero
        };
    }
    
    public record AsyncPerformanceStats
    {
        public long TotalOperations { get; init; }
        public long FailedOperations { get; init; }
        public long CanceledOperations { get; init; }
        public TimeSpan TotalTime { get; init; }
        public TimeSpan AverageTimePerOperation { get; init; }
        
        public double SuccessRate => TotalOperations > 0 ? 
            (TotalOperations - FailedOperations - CanceledOperations) / (double)TotalOperations : 0;
    }
}

2. 异步架构设计模式

// 异步消息处理模式
public class AsyncMessageProcessor
{
    private readonly Channel<Message> _channel;
    private readonly CancellationTokenSource _cts = new();
    private readonly List<Task> _workerTasks = new();
    private readonly ILogger<AsyncMessageProcessor> _logger;
    
    public AsyncMessageProcessor(int workerCount, ILogger<AsyncMessageProcessor> logger)
    {
        _logger = logger;
        _channel = Channel.CreateUnbounded<Message>(new UnboundedChannelOptions
        {
            SingleReader = false,
            SingleWriter = true
        });
        
        // 启动工作线程
        for (int i = 0; i < workerCount; i++)
        {
            _workerTasks.Add(Task.Run(() => ProcessMessagesAsync(_cts.Token)));
        }
    }
    
    public async Task EnqueueAsync(Message message)
    {
        await _channel.Writer.WriteAsync(message, _cts.Token);
    }
    
    private async Task ProcessMessagesAsync(CancellationToken cancellationToken)
    {
        await foreach (var message in _channel.Reader.ReadAllAsync(cancellationToken))
        {
            try
            {
                await ProcessMessageAsync(message);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "处理消息时发生错误: {MessageId}", message.Id);
            }
        }
    }
    
    private async Task ProcessMessageAsync(Message message)
    {
        using var activity = DiagnosticSource.StartActivity("ProcessMessage", message);
        
        // 模拟消息处理
        await Task.Delay(TimeSpan.FromMilliseconds(message.ProcessingTimeMs));
        
        _logger.LogInformation("消息 {MessageId} 处理完成", message.Id);
    }
    
    public async Task StopAsync()
    {
        _channel.Writer.Complete();
        _cts.Cancel();
        
        await Task.WhenAll(_workerTasks);
    }
}

public record Message(string Id, int ProcessingTimeMs);

// 异步限流器
public class AsyncRateLimiter
{
    private readonly SemaphoreSlim _semaphore;
    private readonly TimeSpan _timeWindow;
    private readonly int _maxRequests;
    private DateTime _windowStart;
    private int _requestCount;
    
    public AsyncRateLimiter(int maxRequests, TimeSpan timeWindow)
    {
        _semaphore = new SemaphoreSlim(1, 1);
        _maxRequests = maxRequests;
        _timeWindow = timeWindow;
        _windowStart = DateTime.UtcNow;
        _requestCount = 0;
    }
    
    public async Task<T> ExecuteAsync<T>(Func<Task<T>> operation)
    {
        await WaitForSlotAsync();
        
        try
        {
            return await operation();
        }
        finally
        {
            Interlocked.Increment(ref _requestCount);
        }
    }
    
    private async Task WaitForSlotAsync()
    {
        while (true)
        {
            await _semaphore.WaitAsync();
            
            try
            {
                var now = DateTime.UtcNow;
                if (now - _windowStart >= _timeWindow)
                {
                    // 时间窗口重置
                    _windowStart = now;
                    _requestCount = 0;
                }
                
                if (_requestCount < _maxRequests)
                {
                    return; // 有可用的槽位
                }
                
                // 计算需要等待的时间
                var waitTime = _windowStart + _timeWindow - now;
                if (waitTime > TimeSpan.Zero)
                {
                    await Task.Delay(waitTime);
                }
            }
            finally
            {
                _semaphore.Release();
            }
        }
    }
}

总结

C#异步编程的核心在于理解任务调度、同步上下文和资源生命周期管理:

关键问题总结

  1. 🔒 死锁风险:同步上下文中的阻塞等待导致死锁
  2. 🚀 性能瓶颈:不必要的任务分配和上下文切换
  3. 🗑️ 资源泄漏:未正确实现IAsyncDisposable
  4. ⏱️ 取消困难:未正确传递CancellationToken
  5. 🐛 调试复杂:异步栈追踪信息丢失

解决方案优先级

  1. 使用ConfigureAwait(false)避免不必要的上下文切换
  2. 实现IAsyncDisposable正确管理异步资源
  3. 使用ValueTask减少热点路径的内存分配
  4. 正确传递CancellationToken支持取消操作
  5. 使用Channel等高级结构处理数据流

最佳实践检查清单

  • ✅ 异步方法名以Async结尾
  • ✅ 返回Task/Task<T>/ValueTask/ValueTask<T>
  • ✅ 在库代码中使用ConfigureAwait(false)
  • ✅ 正确实现IAsyncDisposable接口
  • ✅ 及时传递CancellationToken参数
  • ✅ 避免在异步方法中使用.Result和.Wait()
  • ✅ 使用Channel等生产级异步数据结构
  • ✅ 实现适当的重试和超时策略

通过系统化地应用这些最佳实践,可以构建出高性能、可维护且健壮的C#异步应用程序。

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容