本文适用于 .NET Framework 4.5 及以上版本。低版本中无此特性。
Task.run
传统的防止大量工作阻塞 UI,用的是线程。现在 C# 发展越来越强大,有很多种方法了,虽然略有不同,但归根到底还是线程。
由 Task 来处理,一是代码更简洁,二是底层交给 .NET,.NET 分配会更合理。
private void button1_Click(object sender, EventArgs e) { SetValue(); } private void SetValue() { Task.Run(() => { Thread.Sleep(2000); // 模拟大量工作阻塞 2 秒 button1.Text = "1"; }); }
如上代码,在点击按钮后,是可以拖动窗口界面的,说明并没有影响 UI。
() => 是 Lambda 表达式,跟 delegate ()一个道理。
以上还没有涉及到返回值,如果要有返回值,就要引入 await、async。
private void button1_Click(object sender, EventArgs e) { SetValue(); } private async void SetValue() { button1.Text = await GetValue(); } private Task<string> GetValue() { return Task.Run(() => { Thread.Sleep(2000); // 模拟大量工作阻塞 2 秒 return "1"; }); }
关于返回值,实际这里有两个层面:
一是函数的返回值:
void 表示函数无返回值。
Task 表示函数返回值是 Task,但是异步无返回值。
二是这个异步的返回值。
Task 表示函数返回值是 Task,但是异步无返回值。
Task<T> 表示函数返回值是 Task<T>,异步返回值是 T。
其实上面是讲了两个知识点:一是 Task,二是 async 和 await:
如果有返回值,就要在返回类型上加上 Task<>,比如:Task<string>。
如果不要返回值,就直接是 Task GetValue()。
由于内部有 await,就必须用 async 标记。
更详细的,请参见:到底是 return await Task.Run 还是 return Task.Run?。
相关阅读
Task 类 (System.Threading.Tasks) | Microsoft Docs
使用 Async和 Await 的任务异步编程 (TAP) 模型 (C#) | Microsoft Docs
Task 类 (System.Threading.Tasks) | Microsoft Docs
Task<TResult> 类 (System.Threading.Tasks) | Microsoft Docs