将 Task.Run 用于 IO 绑定工作以避免更新方法签名

Using Task.Run for IO bound work to avoid updating method signatures

提问人:David Klempfner 提问时间:10/17/2023 最后编辑:David Klempfner 更新时间:10/17/2023 访问量:34

问:

此方法包含一堆 Redis 代码,并在许多地方调用,并且是深度方法调用堆栈的一部分:

public void Save()
{            
    Task.Run(async () =>
    {
        var transaction = cache.CreateTransaction();
        var _ = transaction.StringSetAsync();
        _ = transaction.SetAddAsync();      
        await transaction.ExecuteAsync();
    }).Wait();
}

我知道线程池线程将用于完成这项工作,并且调用线程将通过调用被阻止,并且在等待 Redis 代码完成时将无法再接受任何 ASP.NET 请求。Wait()

这种阻塞是否微不足道,足以保证保持代码的原样,以避免必须更新调用此代码的所有方法的签名以包含 /?asyncawait

另外,因为只有 ed 在委托中,所以可以在上面的 s 完成之前运行吗?transaction.ExecuteAsync()awaittransaction.ExecuteAsync()Task

asp.net 异步 async-await task-parallel-library net-4.7.2

评论

1赞 Panagiotis Kanavos 10/17/2023
改为异步。开销很大,有 2 个线程阻塞。每个 HTTP 请求都已由不同的线程池线程提供服务。这会阻止当前线程池线程,然后启动另一个线程池线程,该线程除了等待 IO 完成之外什么都不做。你最终会得到两个被阻塞的线程。如果本身是异步的,则不会阻止任何线程。在等待时,将释放请求线程以处理其他请求SaveTask.Run().Wait()Save
3赞 Panagiotis Kanavos 10/17/2023
顺便说一句,为什么 etc 被忽略了?这至少会导致争用条件,甚至可能丢失更新。 可以在之前的通话之前轻松完成StringSetAsyncExecuteAsync
1赞 Panagiotis Kanavos 10/17/2023
why two threads are blocked代码同时阻塞了请求线程用于执行 的线程。如果你使用没有线程将被阻止Task.Runasync/await
1赞 Panagiotis Kanavos 10/17/2023
事实上,确切的问题无法回答,因为它完全取决于项目的具体情况。它可以很容易地关闭为 .Would this blocking be insignificant enough to warrant keeping the codeopinion-based
1赞 David Klempfner 10/17/2023
“另一个线程被浪费在启动 lambda 上”——你无法避免一个线程运行 redis 代码。它要么发生在主线程上,要么发生在线程池线程中。所以我认为你不能说两个线程浪费了一个线程被阻塞。它只有一个线程被阻止。你声称浪费了两条线,瑞安说这不是真的。这次讨论的重点是澄清哪个是正确的。这对我来说是一次很好的学习经历,无论它是否与我提出的确切问题有关。

答: 暂无答案