这真的是异步的吗?IEnumerable< T>扩展
本文关键字:IEnumerable 扩展 真的 异步 | 更新日期: 2023-09-27 18:17:00
public static async Task<T> FirstIfNotNullOrEmptyAsync<T>(this Task<IEnumerable<T>> obj) where T : class
{
var first = await Task.WhenAny(obj);
return first?.Result?.FirstOrDefault() ?? null;
}
下面是显示完整
的另外两个方法主方法(在这种情况下将只返回集合中的项或集合为空)
private async Task<IEnumerable<T>> fetchRecordsAsync(SqlCommand SqlCommand, bool isSingleRecord)
{..some code...}
下面是将获取集合并只传递T的调用者:
protected async Task<T> GetSingleRecord(SqlCommand SqlCommand)
{
return await fetchRecordsAsync(SqlCommand, true).FirstIfNotNullOrEmptyAsync();
}
这是正确的方式与IEnumerable的异步扩展工作,或者它将做一个同步?
我真的需要创建另一个任务(首先)吗?
这真的是异步吗?
是的。await Task.WhenAny
将返回第一个完成的任务。在这样的任务(一个已完成的任务)上使用.Result
不会导致同步等待。
顺便说一句,你不需要使用Task.WhenAny
,你的方法可以简化如下:
public static async Task<T> FirstIfNotNullOrEmptyAsync<T>(
this Task<IEnumerable<T>> obj) where T : class
{
var result = await obj;
return result?.FirstOrDefault();
}
它将异步地完成所有的工作,尽管那里有很多不必要的(尽管不是有害的,除了非常小的额外开销)。
当你只传递一个任务时,调用WhenAny
是没有意义的。你不妨等待任务本身;它做同样的事情。
写?? null
没有意义。如果为"null
",则设置为"null
"。它已经是null
了,所以你可以把它留下。
你也没有将一个空的Task
传递给FirstIfNotNullOrEmptyAsync
,你也不应该这样做。您也可能不应该为结果生成null
IEnumerable
。如果没有条目,你应该有一个空的序列。
也没有理由将该方法限制为仅适用于类序列。如果有人想使用值类型,没有真正的理由阻止他们。
调整方法的名称也是有意义的,这样它的名称就反映了它实际在做什么。
所以现在所有这些都可以归结为:
public static async Task<T> FirstOrDefaultAsync<T>(this Task<IEnumerable<T>> task)
{
return (await task).FirstOrDefault();
}
你的另一个方法也没有理由是async
,因为你从来没有对等待的值做任何事情,除了在Task
中重新包装它并返回它。只要返回Task
,你有:
protected Task<T> GetSingleRecordAsync(SqlCommand SqlCommand)
{
return fetchRecordsAsync(SqlCommand, true)
.FirstOrDefaultAsync();
}