c#中的task类用于处理异步操作,通过封装耗时任务并使其在后台运行,避免阻塞主线程。1. task.run() 是最常用方法,适合将同步代码异步化,默认使用线程池;2. new task().start() 提供更细粒度控制,适合延迟启动或需额外配置的任务;3. task.factory.startnew() 功能强大但复杂,适用于需要高级控制的场景。相比直接使用thread,task利用线程池提升效率,并与async/await集成,简化异步编程模型。异常可通过 await 或检查 exception 属性捕获,取消则通过 cancellationtoken 实现,确保任务安全退出,从而构建更稳定、响应性更强的应用程序。

C#里的
Task
Task.Run()
Task
Start()
Task
async
await
Task
当你需要执行一个操作,比如从网络下载数据、读写大文件、或者进行复杂的计算,这些操作如果直接在UI线程或者主线程上执行,就会导致程序“假死”。
Task
创建
Task
Task.Run()
使用 Task.Run()
// 假设有一个耗时操作
string DoSomethingTimeConsuming()
{
System.Threading.Thread.Sleep(2000); // 模拟耗时2秒
return "操作完成!";
}
// 创建并启动一个任务
Task<string> myTask = Task.Run(() => DoSomethingTimeConsuming());
// 你可以在这里做其他事情,不用等待任务完成
Console.WriteLine("任务已启动,我正在做别的事情...");
// 当你需要结果时,使用await等待
string result = await myTask;
Console.WriteLine(result);Task.Run()
使用 new Task()
Start()
Task
Start()
Task<int> calculateTask = new Task<int>(() =>
{
Console.WriteLine("开始复杂计算...");
System.Threading.Thread.Sleep(3000); // 模拟计算3秒
return 123 + 456;
});
Console.WriteLine("任务已定义,但尚未启动。");
// 可以在某个条件满足时再启动
calculateTask.Start();
Console.WriteLine("任务已显式启动。");
int sum = await calculateTask;
Console.WriteLine($"计算结果: {sum}");这种方式给你的控制权更多,但通常不如
Task.Run()
Task.Run()
使用 Task.Factory.StartNew()
Task.Run()
Task.Factory.StartNew()
Task.Run()
Task<double> powerTask = Task.Factory.StartNew(() =>
{
Console.WriteLine("开始幂运算...");
return Math.Pow(2, 10);
});
double powerResult = await powerTask;
Console.WriteLine($"2的10次方: {powerResult}");除非你需要非常细粒度的控制,比如指定
TaskCreationOptions
LongRunning
Task.Run()
很多人刚接触异步编程时,可能会想到直接用
Thread
Thread
Task
Thread
一个主要原因是线程池的利用。每次创建和销毁一个
Thread
Task
其次是异步编程模型的集成。
Task
async/await
Task
async/await
async/await
Thread
Task
Task.Wait()
Task.ContinueWith()
Task.WhenAll()
Task.WhenAny()
还有就是错误处理和上下文传递。在
Task
await
Task.Exception
Thread
Task
所以,总的来说,
Task
这两个方法都能启动一个任务,但它们在行为上确实有一些细微但重要的区别,这决定了你在不同场景下应该选择哪个。
最核心的区别在于任务的创建和启动时机。
Task.Run(Action action)
Task.Run(Func<TResult> function)
Task.Run()
Action
Func
Task.Run()
Task
优点:
Task.Run()
缺点:
使用场景: 绝大多数情况下,当你需要执行一个后台操作时,都应该优先考虑
Task.Run()
new Task(Action action)
new Task(Func<TResult> function)
task.Start()
new Task()
Task
Created
Start()
优点:
Start()
Created
Task
缺点:
Start()
Start()
Start()
async/await
Task
Task<T>
Start
使用场景: 比较少见,通常是在需要延迟启动、或者在任务启动前进行一些复杂设置的场景下才考虑。例如,你可能有一个任务队列,任务进入队列时先实例化,然后由一个调度器统一
Start()
总结一下,如果你的目标是简单地把一个同步操作扔到后台执行,让它不阻塞当前线程,那么
Task.Run()
new Task().Start()
在异步编程中,正确地处理异常和任务取消是构建健壮应用的关键。如果处理不好,轻则程序崩溃,重则资源泄露或逻辑错误。
Task
async/await
使用 await
try-catch
await
Task
Task
await
try-catch
async Task SimulateErrorAsync()
{
Console.WriteLine("任务开始,准备抛出异常...");
await Task.Delay(1000); // 模拟一些工作
throw new InvalidOperationException("哎呀,任务出错了!");
}
async Task CallWithErrorHandling()
{
try
{
await SimulateErrorAsync();
Console.WriteLine("任务成功完成(这条不会打印)");
}
catch (InvalidOperationException ex)
{
Console.WriteLine($"捕获到异常: {ex.Message}");
}
catch (Exception ex) // 捕获其他类型的异常
{
Console.WriteLine($"捕获到未知异常: {ex.Message}");
}
}
// 调用示例
// await CallWithErrorHandling();这种方式最直观,也最符合我们处理同步异常的习惯。
检查 Task.Exception
Task
await
AggregateException
Task
Exception
Task failingTask = Task.Run(() =>
{
Console.WriteLine("后台任务开始,即将抛出异常...");
throw new DivideByZeroException("除零错误!");
});
// 不使用await,让任务在后台运行
Console.WriteLine("主线程继续执行...");
try
{
// 尝试等待任务完成,这时如果任务失败,异常会被抛出
failingTask.Wait(); // 或者 failingTask.Result;
}
catch (AggregateException ae)
{
Console.WriteLine($"捕获到聚合异常,包含 {ae.InnerExceptions.Count} 个内部异常:");
foreach (var ex in ae.InnerExceptions)
{
Console.WriteLine($"- {ex.GetType().Name}: {ex.Message}");
}
}AggregateException
Task
Task.WhenAll
Task
注意: 如果不
await
Wait()
Result
Task.Exception
Task
任务取消是一种协作式的机制,意味着任务本身需要主动检查取消请求并响应。这比简单地“杀死”一个线程要优雅和安全得多。
使用 CancellationTokenSource
CancellationToken
CancellationTokenSource
CancellationToken
CancellationTokenSource
async Task DoWorkWithCancellation(CancellationToken cancellationToken)
{
for (int i = 0; i < 10; i++)
{
// 每次循环都检查是否收到取消请求
if (cancellationToken.IsCancellationRequested)
{
Console.WriteLine("任务收到取消请求,准备退出。");
// 可以选择抛出OperationCanceledException
cancellationToken.ThrowIfCancellationRequested();
// 或者直接return;
// return;
}
Console.WriteLine($"正在执行工作... 步骤 {i + 1}");
await Task.Delay(500, cancellationToken); // Task.Delay也支持CancellationToken
}
Console.WriteLine("任务正常完成。");
}
async Task RunCancellableTask()
{
using (var cts = new CancellationTokenSource())
{
Task longRunningTask = DoWorkWithCancellation(cts.Token);
// 模拟一段时间后发出取消请求
await Task.Delay(2000);
Console.WriteLine("发出取消请求...");
cts.Cancel();
try
{
await longRunningTask;
}
catch (OperationCanceledException)
{
Console.WriteLine("任务被成功取消了!");
}
catch (Exception ex)
{
Console.WriteLine($"任务中发生其他异常: {ex.Message}");
}
}
}
// 调用示例
// await RunCancellableTask();cancellationToken.ThrowIfCancellationRequested()
OperationCanceledException
await
return
RanToCompletion
Canceled
OperationCanceledException
正确地处理异常和取消,能够让你的异步程序更加稳定、响应迅速,并且易于调试。
以上就是C#的Task类是用来做什么的?如何创建任务?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号