单元测试问题:如何确保断言前等待所有线程执行完成?
问题根源
你遇到的核心问题是:用Thread执行async void委托时,线程会在await处提前退出。thread.Join()只能等待线程本身的执行流程结束,而不等await之后的异步逻辑完成,导致断言时部分GetMemoryAsync()还没执行完毕,断言失败。
解决方案
方案1:改用Task(推荐,符合异步编程最佳实践)
直接使用Task管理异步操作,用Task.WhenAll等待所有任务完成,同时将测试方法改为async Task类型:
[Test] public async Task Test_Racing_Condition() { //Arrange & Act var tasks = new Task[20]; for (int i = 0; i < tasks.Length; i++) { tasks[i] = _memory.GetMemoryAsync(); } // 等待所有异步任务完成 await Task.WhenAll(tasks); //Assert Mock.Assert(() => _memory.GetMemoryAsync(), Occurs.Exactly(20)); }
方案2:如果必须用Thread,同步等待异步方法
避免使用async void,在Thread内部同步等待异步方法完成,确保线程会等到GetMemoryAsync()执行完再结束:
[Test] public void Test_Racing_Condition() { //Arrange & Act var threads = new Thread[20]; for (int i = 0; i < threads.Length; i++) { // 用.GetAwaiter().GetResult()同步等待异步方法完成,防止线程提前退出 threads[i] = new Thread(() => _memory.GetMemoryAsync().GetAwaiter().GetResult()); } foreach (Thread thread in threads) { thread.Start(); } foreach (var thread in threads) { thread.Join(); } //Assert Mock.Assert(() => _memory.GetMemoryAsync(), Occurs.Exactly(20)); }
关键说明
async void仅适用于事件处理程序,在Thread委托这类场景中会导致异步操作不受跟踪,线程提前终止。- 异步测试优先采用
async Task类型的测试方法,配合Task.WhenAll是最可靠的异步等待方式。
内容的提问来源于stack exchange,提问作者DanielV
相关产品推荐
相关产品推荐

