我有两个代码段,我试图使用Func
static void Main(string[] args)
{
Func<Task<int>> getter = async () => await Get();
int x = getter().Result;
Console.WriteLine("hello : " + x);
}
static async Task<int> Get()
{
await Task.Delay(1000);
return 1;
}
static void Main(string[] args)
{
Func<Task<int>> getter = () => Get();
int x = getter().Result;
Console.WriteLine("hello : " + x);
}
static async Task<int> Get()
{
await Task.Delay(1000);
return 1;
}
不同之处在于出现错误时的堆栈跟踪。如果您像下面这样稍微修改一下代码,您就会看到结果是如何不同的。
internal class Example1
{
public static void Main(string[] args)
{
Func<Task<int>> getter = async () => await Get();
int x = getter().Result;
Console.WriteLine("hello : " + x);
}
static async Task<int> Get()
{
throw new Exception("test");
await Task.Delay(1000);
return 1;
}
}
internal class Example2
{
public static void Main(string[] args)
{
Func<Task<int>> getter = () => Get();
int x = getter().Result;
Console.WriteLine("hello : " + x);
}
static async Task<int> Get()
{
throw new Exception("test");
await Task.Delay(1000);
return 1;
}
}
当Example1抛出异常时,您将看到如下所示的堆栈跟踪。查看堆栈跟踪,您知道Get()方法是从匿名方法调用的。
This exception was originally thrown at this call stack:
StackOverflow.CSharp.Example1.Get() in Example.cs
StackOverflow.CSharp.Example1.Main.AnonymousMethod__0_0() in Example.cs
然而,当Example2抛出异常时,堆栈跟踪被减少,并且不显示Get()是从哪里被调用的。可能很难追踪潜在的问题。
This exception was originally thrown at this call stack:
StackOverflow.CSharp.Example2.Get() in Example.cs
在我们的项目中,我们更倾向于使用async/await的第一种方法。
对于这样一个微不足道的情况,这两个示例将或多或少地执行相同的操作。
根据经验,您应该直接返回任务,而不必等待。也就是说,当你调用一个方法返回一个任务,而不做任何处理的结果。但这主要是由于代码风格的原因,即避免不必要的关键字,可能会混淆读者。因此,首选例2。
离岸金融中心。在您的具体示例中,您可能根本不应该使用async,而应该使用Thread.Sleep
。在UI程序中,您应该避免使用.Result
,因为它会阻塞UI线程,并增加死锁的风险。