不同的版本
不简洁版(传统写法,使用 BeginInvoke/EndInvoke 或 Task.Factory.StartNew + ContinueWith)csharp
s_calculateButton.Clicked += (o, e) =>
{
// 手动创建 Task 并用 ContinueWith 接后续操作
Task.Factory.StartNew(() => CalculateDamageDone())
.ContinueWith(task =>
{
// 注意:ContinueWith 默认不会自动捕获上下文,需要用 TaskScheduler.FromCurrentSynchronizationContext()
// 否则 DisplayDamage 会在后台线程运行,会抛异常
if (task.IsFaulted)
{
// 处理异常(可选)
DisplayError(task.Exception);
}
else
{
DisplayDamage(task.Result);
}
},
TaskScheduler.FromCurrentSynchronizationContext()); // 确保回调回到 UI 线程
};
更老的写法(.NET 4.0 之前或 WinForms 风格)csharp
s_calculateButton.Clicked += (o, e) =>
{
// 使用 Task.Run 以前的经典做法
var task = new Task<DamageResult>(() => CalculateDamageDone());
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
// 处理错误
}
else
{
// 回到 UI 线程
this.Invoke((MethodInvoker)delegate
{
DisplayDamage(t.Result);
});
}
}, TaskContinuationOptions.OnlyOnRanToCompletion);
task.Start();
};
还有更原始的写法(完全不用 Task,使用 BackgroundWorker)csharp
private void s_calculateButton_Click(object sender, EventArgs e)
{
var worker = new BackgroundWorker();
worker.DoWork += (s, args) =>
{
args.Result = CalculateDamageDone();
};
worker.RunWorkerCompleted += (s, args) =>
{
if (args.Error != null)
{
// 处理异常
}
else
{
DisplayDamage((DamageResult)args.Result);
}
};
worker.RunWorkerAsync();
}
总结对比
| 方式 | 代码量 | 可读性 | 现代性 | 是否需要手动管理 UI 线程 |
|---|---|---|---|---|
| 你原来的简洁版 (async/await + Task.Run) | 3 行 | ★★★★★ | ★★★★★ | 自动处理 |
| Task.Factory + ContinueWith | 10+ 行 | ★★★☆☆ | ★★★★☆ | 需要手动加 SynchronizationContext |
| Task + Invoke | 12+ 行 | ★★☆☆☆ | ★★☆☆☆ | 手动管理 UI 线程 |
| BackgroundWorker | 15+ 行 | ★★☆☆☆ | ★☆☆☆☆ | 自动回到 UI 线程 |
所以你的原版就是目前最推荐、最简洁、最优雅的写法,完全没必要写成"不简洁版"。
除非你需要兼容 .NET 3.5 或以下(几乎不可能),否则就继续用你现在的写法就好!