.NET中如何在同步代码块中调用异步方法
更新记录
本文迁移自Panda666原博客,原发布时间:2021年7月2日。
在同步代码块中调用异步方法,方法有很多。
一、对于有返回值的Task
在同步代码块中直接访问 Task 的 Result 属性,这会阻塞调用线程直到返回Result为止。
代码实例:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace PandaTestClass
{
class Program
{
private static async Task<(string, string)> DoSomething()
{
//用于返回值
(string, string) result = ("?", "?");
//任务1
await Task.Run(() => {
//模拟耗时任务
for (int i = 0; i <= 100; i += 20)
{
Console.WriteLine($"任务1,当前执行到:{i}%");
Thread.Sleep(TimeSpan.FromSeconds(1));
}
//写入返回值
result.Item1 = "任务1完成";
});
//任务2
await Task.Run(() => {
//模拟耗时任务
for (int i = 0; i <= 100; i += 20)
{
Console.WriteLine($"任务2,当前执行到:{i}%");
Thread.Sleep(TimeSpan.FromSeconds(1));
}
//写入返回值
result.Item2 = "任务2完成";
});
//确保任务执行完成
Task.WaitAll(new Task[] { });
//返回返回值
return result;
}
static void Main(string[] args)
{
//同步块中使用异步方法
//这里会阻塞主线程
(string t1, string t2) result = DoSomething().Result;
//执行完成
Console.WriteLine("DoSomething Success");
//获得结果集1
Console.WriteLine(result.t1);
//获得结果集2
Console.WriteLine(result.t2);
//wait
Console.WriteLine("Main Suceess");
Console.ReadKey();
}
}
}
二、使用Task.Run()方法包裹
强烈推荐该方法。
代码实例:
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace PandaTestClass
{
class Program
{
///
/// 异步方法
///
///
private static async Task<(string, string)> DoSomething()
{
//用于返回值
(string, string) result = ("?", "?");
//任务1
await Task.Run(() => {
//模拟耗时任务
for (int i = 0; i <= 100; i += 20)
{
Console.WriteLine($"任务1,当前执行到:{i}%");
Thread.Sleep(TimeSpan.FromSeconds(1));
}
//写入返回值
result.Item1 = "任务1完成";
});
//任务2
await Task.Run(() => {
//模拟耗时任务
for (int i = 0; i <= 100; i += 20)
{
Console.WriteLine($"任务2,当前执行到:{i}%");
Thread.Sleep(TimeSpan.FromSeconds(1));
}
//写入返回值
result.Item2 = "任务2完成";
});
//确保任务执行完成
Task.WaitAll(new Task[] { });
//返回返回值
return result;
}
static void Main(string[] args)
{
//同步块中使用异步方法
//这里会阻塞主线程
Task<(string t1, string t2)> returnValue = Task.Run(async () => {
(string t1, string t2) r = await DoSomething();
return r;
});
//执行完成
//获得结果集1
Console.WriteLine(returnValue.Result.t1);
//获得结果集2
Console.WriteLine(returnValue.Result.t2);
//wait
Console.WriteLine("Main Suceess");
Console.ReadKey();
}
}
}