gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 20:23:41 25 4
gpt4 key购买 nike

我正在尝试将以下方法(简化示例)转换为异步方法,如 cacheMissResolver就时间而言(数据库查找、网络调用)调用可能很昂贵:

// Synchronous version
public 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 attempts
public 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 语句的正确方法? (我不能在 lock 语句的主体中等待。)

我应该制作 cacheMissResolver 吗? Func<Task<Thing>> 类型的参数反而?尽管这给调用方带来了确保解析器函数异步的负担(包装在 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 bound 工作。 (虽然仍然通过简单地让调用者自己使用 Task.Run 来支持 CPU 绑定(bind)工作,如果那是他们想做的。)


除此之外,请注意 await Task.FromResult(...); 没有意义在 Task 中包装一个值只是立即解开它是没有意义的。在这种情况下直接使用结果即可,在这种情况下,直接返回缓存的值。您所做的并不是真的错误,它只是不必要地使代码复杂化/混淆。

关于c# - 在 C# 中将方法转换为异步的正确方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30629670/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com