深入分析C# Task攻略
什么是C# Task?
C# Task是一种异步编程模型,用于执行长时间运行的计算或I/O操作。Task API提供了执行和计划多个异步操作的方法,例如等待任务完成、等待任意完成,或等待任意取消。Task API是.NET Framework 4.5版本中Task Parallel Library (TPL)的一部分。
如何使用Task?
使用Task,可以将任务定义为一个返回值为TResult类型的异步方法。下面是一个例子:
public async Task<string> DownloadStringFromUrl(string url)
{
using (var client = new HttpClient())
{
return await client.GetStringAsync(url);
}
}
- 这个方法返回类型为
Task<string>
,表示异步执行后会得到一个返回类型为string的结果 async
关键词告诉编译器这是一个异步方法await
关键词告诉编译器需要等待GetStringAsync
方法执行完成才能继续执行下面的代码
接下来让我们看一下,如何开始一个Task并等待它完成:
var task = DownloadStringFromUrl("https://www.example.com");
var result = await task;
DownloadStringFromUrl
方法会异步执行- 代码不会阻塞在这里,可以执行其他任务
- 当Task完成后,
await
将强制代码等待Task的完成
Task的异常处理
处理Task方法中的异常是很重要的。如果没有适当的异常处理会导致程序崩溃,或者让程序处于死锁状态。下面是一个示例:
public async Task<string> DownloadStringFromUrl(string url)
{
using (var client = new HttpClient())
{
try
{
return await client.GetStringAsync(url);
}
catch (Exception e)
{
return e.Message;
}
}
}
在上面的例子中,我们指定了异常类型,以在发生异常(例如无法连接到服务器)时返回异常消息而不是让程序崩溃。
Task取消和超时
Task API提供了取消和超时的功能,以避免长时间运行或长时间等待一个操作的结果。例如,当用户请求取消操作时,可以取消正在执行的Task。下面是执行一个任务时的取消和超时示例:
var cts = new CancellationTokenSource(); // 取消令牌源
var cancellationTask = Task.Factory.StartNew(() =>
{
while (!cts.Token.IsCancellationRequested) // 防止死循环
{
// 执行你的操作
}
}, cts.Token);
// 如果任务超过1分钟没有完成,就取消任务
if (await Task.WhenAny(cancellationTask, Task.Delay(TimeSpan.FromMinutes(1))) == cancellationTask)
{
cts.Cancel();
}
CancellationTokenSource
用于取消TaskTask.Delay
可以设置超时时间await Task.WhenAny
可以等待多个Task中的一个完成,如果cancellationTask先完成,则取消任务
示例1:使用Task下载多个url
public async Task<IEnumerable<string>> DownloadManyUrls(IEnumerable<string> urls, CancellationToken token)
{
var tasks = urls.Select(url => DownloadStringFromUrl(url, token)); // 创建下载任务
var results = await Task.WhenAll(tasks); // 等待所有任务完成
return results;
}
Select
方法将每个字符串转换为Task<string>
WhenAll
方法等待所有的Task完成,返回所有Task的结果
示例2:发送邮件并处理超时
public async Task SendEmailAsync(MailMessage message, int timeoutSeconds)
{
using (var smtp = new SmtpClient())
{
var completionSource = new TaskCompletionSource<bool>();
smtp.SendCompleted += (sender, args) =>
{
if (args.Cancelled)
{
completionSource.SetCanceled();
}
else if (args.Error != null)
{
completionSource.SetException(args.Error);
}
else
{
completionSource.SetResult(true);
}
};
await smtp.SendMailAsync(message);
if (await Task.WhenAny(completionSource.Task, Task.Delay(TimeSpan.FromSeconds(timeoutSeconds))) != completionSource.Task)
{
throw new TimeoutException("超时了!");
}
}
}
- 使用
TaskCompletionSource
将“封闭”的方法(SendCompleted
)转换为异步模型 WhenAny
等待两个任务中的任何一个完成,如果超时,抛出一个TimeoutException
异常
总结
Task是一种强大灵活的C#异步编程模型。通过使用Task API,可以更轻松地管理长时间运行或I/O密集型操作,同时保持代码的简洁性和易于维护性。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入分析C# Task - Python技术站