gpt4 book ai didi

c# - async & await - 处理对同一方法的多次调用 - 锁定/等待彼此?

转载 作者:行者123 更新时间:2023-11-30 21:47:12 25 4
gpt4 key购买 nike

我有一个复杂的基于任务/锁的困惑来执行“长”数据操作,我正在尝试用异步/等待替换它。我是异步等待的新手,所以我担心我犯了一些大错误。

为了简化事情,我的 UI 有几个页面依赖于相同的数据。现在,我只需要获取这些数据一次。所以我缓存它,以后的调用只是从缓存“CachedDataObjects”中获取它,而不是每次都进行长调用。

像这样(半伪代码):

    private Dictionary<Guid,List<Data>> CachedDataObjects;

public async Task<List<Data>> GetData(Guid ID)
{
List<Data> data = null;

//see if we have any cached
CachedDataObjects.TryGetValue(ID, out data);

if (data == null)
{
if (ConnectedToServer)
{
data = new List<Data>();
await Task.Run(() =>
{
try
{
//long data call
data = Service.GetKPI(ID);
}
catch (Exception e)
{
//deal with errors (passes an action to do if resolved)
PromptForConnection(new Task(async () => { data = await GetData(ID); }), e);
}
});
}

CachedDataObjects.Add(ID, data);
}
return data;
}

但是,由于异步调用的性质,此方法会在两个页面被触发时被调用。

因此,出现异常 - 具有该 ID 的项目已添加到字典中。即使我修补了那个问题,潜在的问题仍然存在。 Data 对象将是不同的版本,我正在执行两个网络调用,而我应该只有一个等等。

之前,我通过将整个方法封装在一个 lock 语句中来“破解”了一个解决方案——因此只允许对其进行一次调用。我所有的数据加载都是在后台工作人员中完成的,第一个进行调用,一旦完成,其他人就会解锁以执行快速抓取。

但是我不能在异步方法中使用lock,反正这个方案感觉不太好。

异步方法是否可以“等待”其他异步调用完成?

最佳答案

你的问题是你是await在将任务添加到字典之前先执行任务。在这种情况下,您需要将任务 添加到字典中,以便调用此方法的下一个页面将获得相同的任务:

public Task<List<Data>> GetData(Guid ID)
{
Task<List<Data>> task = null;
CachedDataObjects.TryGetValue(ID, out task);
if (task == null)
{
if (ConnectedToServer)
{
task = Task.Run(() =>
{
try
{
//long data call
return Service.GetKPI(ID);
}
catch (Exception e)
{
//deal with errors
}
});
}
DataObjects.Add(ID, task);
}
return task;
}

这将缓存任务。但是,如果 //deal with errors传播异常,那么这也将缓存该异常。

为了避免这种情况,你可以使用更复杂的代码,或者你可以采用我的 AsyncLazy<T> type :

private readonly ConcurrentDictionary<Guid, AsyncLazy<List<Data>>> CachedDataObjects;
public Task<List<Data>> GetData(Guid ID)
{
var lazy = CachedDataObjects.GetOrAdd(ID, id =>
new AsyncLazy<List<Data>>(() => Task.Run(() =>
{
try
{
return Service.GetKPI(ID);
}
catch (Exception e)
{
//deal with errors
throw;
}
}, AsyncLazyFlags.RetryOnFailure | AsyncLazyFlags.ExecuteOnCallingThread)));
return lazy.Task;
}

关于c# - async & await - 处理对同一方法的多次调用 - 锁定/等待彼此?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38635349/

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