类似于在同步代码中实现需要任务返回类型的接口,不过我很好奇是否应该忽略我的情况生成的编译器错误。
假设我有一个这样的接口:
public interface IAmAwesome {
Task MakeAwesomeAsync();
}
在某些实现中,使用
在其他情况下,也许很少,只需要一个简单的同步方法就可以使Awesome。我们假设实现如下所示:
public class SimplyAwesome : IAmAwesome {
public async Task MakeAwesomeAsync() {
// Some really awesome stuff here...
}
}
null
此方法缺少'await'运算符,将同步运行。考虑使用
编译器实际上是在建议这个解决方案:
public class SimplyAwesome : IAmAwesome {
public async Task MakeAwesomeAsync() {
await Task.Run(() => {
// Some really awesome stuff here, but on a BACKGROUND THREAD! WOW!
});
}
}
我的问题是-什么应该决定当我选择忽略这个编译器警告?在某些情况下,工作是如此的简单,以至于为它产生一个线程是不可否认的适得其反。
如果您确实希望同步地执行工作,您知道
当然,另一种选择是不使用
当我选择忽略此编译器警告时,应如何确定?在某些情况下,工作是如此的简单,以至于为它产生一个线程是不可否认的适得其反。
编译器没有说“在此方法中使用Task.Run”。它只是告诉您,您为他准备了一个
您可以采取三种方法:
A.您可以忽略编译器警告,一切仍将执行。请注意,生成状态机会有轻微的开销,但是您的方法调用将同步执行。如果操作很耗时,并且可能导致方法执行发出阻塞调用,这可能会使使用此方法的用户感到困惑。
b.将“AWESOME”的生成分离为同步接口和异步接口:
public interface MakeAwesomeAsync
{
Task MakeAwesomeAsync();
}
public interface MakeAwesome
{
void MakeAwesome();
}
C.如果操作不太耗时,您可以简单地使用
正如其他人已经指出的,你有三种不同的选择,所以这是一个见仁见智的问题:
我建议返回一个已经完成的任务:
public class SimplyAwesome : IAmAwesome
{
public Task MakeAwesomeAsync()
{
// run synchronously
return TaskExtensions.CompletedTask;
}
}
原因有几个:
Servy指出,返回任务会改变异常处理的语义。虽然这是真的,但我认为这不是问题。
首先,大多数
其次,即使。NET Framework的任务返回方法也会同步抛出异常。例如,
try
{
Task.Delay(-2);
}
catch (Exception e)
{
Console.WriteLine(e);
}
由于。NET开发人员需要在。NET中同步遇到异常,因此合理的做法是,他们也应该从您的代码中排除异常。