在C#中将方法转换为异步的正确方法?

在C#中将方法转换为异步的正确方法?,第1张

概述我试图将以下方法(简化示例)转换为异步,因为cacheMissResolver调用在时间方面可能很昂贵(数据库查找,网络调用): // Synchronous versionpublic class ThingCache{ private static readonly object _lockObj; // ... other stuff public Thing 我试图将以下方法(简化示例)转换为异步,因为cacheMissResolver调用在时间方面可能很昂贵(数据库查找,网络调用):
// Synchronous versionpublic class ThingCache{    private static Readonly object _lockObj;    // ... other stuff    public Thing Get(string key,Func<Thing> cacheMissResolver)    {        if (cache.Contains(key))            return cache[key];        Thing item;        lock(_lockObj)        {            if (cache.Contains(key))                return cache[key];            item = cacheMissResolver();                cache.Add(key,item);        }        return item;    }}

关于消费异步方法有很多关于在线的材料,但我在生产它们时发现的建议似乎不那么明确.鉴于这是为了成为图书馆的一部分,我的下列任何一种尝试都是正确的吗?

// Asynchronous attemptspublic class ThingCache{    private static Readonly SemaphoreSlim _lockObj = new SemaphoreSlim(1);    // ... other stuff    // attempt #1    public async Task<Thing> Get(string key,Func<Thing> cacheMissResolver)    {        if (cache.Contains(key))            return await Task.Fromresult(cache[key]);        Thing item;        await _lockObj.WaitAsync();        try        {            if (cache.Contains(key))                return await Task.Fromresult(cache[key]);            item = await Task.Run(cacheMissResolver).ConfigureAwait(false);            _cache.Add(key,item);        }        finally        {            _lockObj.Release();        }        return item;    }    // attempt #2    public async Task<Thing> Get(string key,Func<Task<Thing>> cacheMissResolver)    {        if (cache.Contains(key))            return await Task.Fromresult(cache[key]);        Thing item;        await _lockObj.WaitAsync();        try        {            if (cache.Contains(key))                return await Task.Fromresult(cache[key]);            item = await cacheMissResolver().ConfigureAwait(false);            _cache.Add(key,item);        }        finally        {            _lockObj.Release();        }        return item;    }}

使用SemaphoreSlim是否是在异步方法中替换lock语句的正确方法? (我无法在锁定声明的正文中等待.)

我应该使用类型为Func< Task< Thing>>的cacheMissResolver参数代替?虽然这会增加确保解析器func在调用者上是异步的负担(包装在Task.Run中,但我知道如果需要很长时间,它将被卸载到后台线程).

谢谢.

解决方法

Is using SemaphoreSlim the correct way to replace a lock statement in an async method?

是.

Should I make the cacheMissResolver argument of type Func<Task<Thing>> instead?

是.它将允许调用者提供固有的异步 *** 作(例如IO),而不是使其仅适用于长时间运行cpu绑定工作的工作. (通过简单地让调用者自己使用Task.Run来支持cpu绑定工作,如果这是他们想要做的事情.)

除此之外,请注意等待Task.Fromresult(…)没有意义;在Task中包装一个值只是为了立即打开它是没有意义的.只需在这种情况下直接使用结果,在这种情况下,直接返回缓存的值.你正在做的事情并不是真的错,它只是不必要地使代码变得复杂/混乱.

总结

以上是内存溢出为你收集整理的在C#中将方法转换为异步的正确方法?全部内容,希望文章能够帮你解决在C#中将方法转换为异步的正确方法?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1243266.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存