Yuc*_*uck 8 c# multithreading asynchronous task-parallel-library async-await
类似于在同步代码中实现需要Task返回类型的接口,尽管我很好奇我是否应该忽略编译器错误而不是我的情况.
假设我有这样的界面:
public interface IAmAwesome {
Task MakeAwesomeAsync();
}
Run Code Online (Sandbox Code Playgroud)
在一些实现中,通过使用async和异步完成来实现令人敬畏的好处await.这实际上是接口试图允许的内容.
在其他情况下,也许很少见,只需要一个简单的同步方法来制作真棒.所以我们假设实现如下:
public class SimplyAwesome : IAmAwesome {
public async Task MakeAwesomeAsync() {
// Some really awesome stuff here...
}
}
Run Code Online (Sandbox Code Playgroud)
这有效,但编译器警告:
这种方法缺少"等待"运算符并将同步运行.考虑使用
await运算符等待非阻塞API调用,或者"等待TaskEx.Run(...)"在后台线程上执行CPU绑定工作.
编译器实际上是在建议这个解决方案:
public class SimplyAwesome : IAmAwesome {
public async Task MakeAwesomeAsync() {
await Task.Run(() => {
// Some really awesome stuff here, but on a BACKGROUND THREAD! WOW!
});
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是 - 当我选择忽略此编译器警告时应该确定什么?在某些情况下,工作非常简单,为它产生一个线程无疑会适得其反.
Ser*_*rvy 13
如果你确实想要同步进行工作,你知道你的async方法将始终同步运行,并且在这种情况下是理想的,然后一定要忽略警告.如果您了解警告告诉您的内容并感觉它所描述的操作是正确的,那么这不是问题.这是一个警告而不是错误的原因.
当然,另一种选择是不要制作方法async,而只是简单地Task.FromResult用来返回已经完成的任务.它会改变错误处理语义(除非你还捕获所有异常并将它们包装到你返回的任务中),所以至少要注意这一点.如果您确实希望通过结果传播异常Task,则可能值得保留该方法async并禁止警告.
当我选择忽略此编译器警告时应该确定什么?在某些情况下,工作非常简单,为它产生一个线程无疑会适得其反.
编译器并没有说"在此方法中使用Task.Run".它只是告诉你你准备了一个async方法,将async修饰符添加到你的方法声明中,但你实际上并没有等待任何东西.
你可以采取三种方法:
答:你可以忽略编译器警告,一切都会执行.请注意,状态机生成会有轻微的开销,但您的方法调用将同步执行.如果操作耗时并且可能导致方法执行进行阻塞调用,则这可能会使使用此方法的用户感到困惑.
B.将"Awesome"的生成分为同步接口和异步接口:
public interface MakeAwesomeAsync
{
Task MakeAwesomeAsync();
}
public interface MakeAwesome
{
void MakeAwesome();
}
Run Code Online (Sandbox Code Playgroud)
C.如果操作不太耗时,您可以简单地将其包装在Task使用中Task.FromResult.我肯定会在选择之前测量运行CPU绑定操作所需的时间.
正如其他人已经指出的那样,你有3种不同的选择,所以这是一个观点问题:
async并忽略警告async重载async并返回已完成的任务.我建议您返回已完成的任务:
public class SimplyAwesome : IAmAwesome
{
public Task MakeAwesomeAsync()
{
// run synchronously
return TaskExtensions.CompletedTask;
}
}
Run Code Online (Sandbox Code Playgroud)
有几个原因:
async会有一点创建状态机和禁用某些优化(如内联)的开销.await.async.这就像添加while(false){}你的代码一样,它会起到同样的作用,但它并没有传达方法的含义.Servy指出,返回任务会改变异常处理的语义.虽然这是真的,但我认为这不是问题.
首先,大多数async代码调用一个方法并在同一个地方等待返回的任务(即await MakeAwesomeAsync()),这意味着无论方法是否存在,异常都将被抛出到同一个地方async.
其次,甚至.Net框架的Task-returns方法也会同步抛出异常.例如Task.Delay,直接抛出异常而不将其存储在返回的任务中,因此不需要await任务来引发异常:
try
{
Task.Delay(-2);
}
catch (Exception e)
{
Console.WriteLine(e);
}
Run Code Online (Sandbox Code Playgroud)
由于.Net开发人员需要除了在.Net中同步遇到异常外,除了代码之外,它们也应该是合理的.
| 归档时间: |
|
| 查看次数: |
1557 次 |
| 最近记录: |