在此上下文中,Task.Run 和异步任务有什么区别? [重复]

问题描述 投票:0回答:2

有人可以向我解释一下下面两个代码示例的行为有什么区别吗? 哪一种更好/更安全? 这是存储库实现的一个片段。

任务.运行

    public Task<TDocument> FindByIdAsync(string id)
    {
        return Task.Run(() =>
        {
            var objectId = new ObjectId(id);
            var filter = Builders<TDocument>.Filter.Eq(doc => doc.Id, objectId);
            return _collection.Find(filter).SingleOrDefaultAsync();
        });
    }

异步任务

    public async Task<TDocument> FindByIdAsync(string id)
    {
        var objectId = new ObjectId(id);
        var filter = Builders<TDocument>.Filter.Eq(doc => doc.Id, objectId);
        return await _collection.Find(filter).SingleOrDefaultAsync();
    }
c# .net async-await task
2个回答
1
投票

Task.Run
,如docs中所述:

将指定的工作排队在

ThreadPool
上运行,并返回该工作的任务或
Task<TResult>
句柄。

即在这种情况下,它将强制执行线程池上的所有代码。通常

Task.Run
用于 CPU 密集型工作负载,例如,如果
FindByIdAsync
在某些单线程
SynchronizationContext
中执行(例如在桌面应用程序的 UI 线程中),并且
SingleOrDefaultAsync
调用之前的代码计算量很大它可能会导致 UI 冻结,这是不可取的。它还处理
SingleOrDefaultAsync
不是“真正异步”的情况。

另一方面,如果您在没有同步上下文的“普通”ASP.NET Core 中调用此方法,则在这种情况下使用

Task.Run
没有多大意义,第二种方法应该更可取(它应该更性能良好,尽管在很多情况下并不那么明显)。

虽然假设这是用于查询某些数据库/存储的代码,并且客户端很可能是“真正异步”的(尽管存在一些令人讨厌的异常),但是使用第一个而不是第二个并没有多大意义。

另请参阅:


-1
投票

当您想要并行化 CPU 密集型工作时,第一种方法适用。但是,在异步编程的上下文中,它不是最有效的方法,因为它通过启动新任务并在不同线程上运行代码而引入额外的开销。

第二种方法更加高效,是处理异步操作的推荐方法。它不会引入不必要的上下文切换或额外的线程开销,使其成为异步代码的更好选择。

总而言之,

async/await
方法通常对于处理存储库或任何其他异步代码中的异步操作更好、更安全。

更多详细信息:Task.Run vs Async Await

© www.soinside.com 2019 - 2024. All rights reserved.