TaskCompletionSource<T> 的核心作用是:手动控制一个 Task 的完成状态 。它适合把回调、事件、外部信号转成 await 能用的 Task。
基本用法
csharp
var tcs = new TaskCompletionSource<string>(
TaskCreationOptions.RunContinuationsAsynchronously);
// 消费方
string result = await tcs.Task;
// 生产方在回调/事件里完成
tcs.TrySetResult("ok");
常用方法
| 方法 | 作用 |
|---|---|
tcs.Task |
返回等待方使用的 Task |
TrySetResult(v) |
标记成功,返回 bool,重复调用不抛异常 |
TrySetException(ex) |
标记失败 |
TrySetCanceled() |
标记取消 |
SetResult(v) |
强制完成,重复调用会抛 InvalidOperationException |
生产环境建议统一用 TrySet*,避免回调多次触发时崩溃。
桥接事件/回调
csharp
public Task<string> WaitForMessageAsync()
{
var tcs = new TaskCompletionSource<string>(
TaskCreationOptions.RunContinuationsAsynchronously);
void Handler(object? s, string msg)
{
_messageSource.Received -= Handler;
tcs.TrySetResult(msg);
}
_messageSource.Received += Handler;
return tcs.Task;
}
加超时
csharp
var tcs = new TaskCompletionSource<string>(
TaskCreationOptions.RunContinuationsAsynchronously);
var timeout = Task.Delay(3000);
var completed = await Task.WhenAny(tcs.Task, timeout);
if (completed == timeout)
throw new TimeoutException();
return await tcs.Task;
注意:TCS 超时只是让等待方不再等,底层操作不一定真的被取消。
关键点
- 构造时加
RunContinuationsAsynchronously,防止续体在设置结果的线程上同步执行,减少死锁风险。 - TCS 只能完成一次,状态一旦变成 Completed / Faulted / Canceled 就不能再改。
- 需要重复使用时,每次创建新实例,不要复用已完成的 TCS。