gpt4 book ai didi

c# - 对象引用在多层异步等待操作中丢失

转载 作者:太空宇宙 更新时间:2023-11-03 23:27:44 24 4
gpt4 key购买 nike

我遇到了一些行为,这些行为让我对垃圾收集器的异步等待模式的行为感到有些困惑。这是对生产代码的解释。

public async Task CreateProduct(int id)
{
Product result = factory.Create(id);
await AssignPrices(result);
GC.KeepAlive(result);
Assert.That(result.Prices.Count == 1); //this is true
}

public async Task AssignPrices(Product value)
{
foreach (var engine in pricingEngines)
{
await engine.AddPrice(value);
}
}

public class DefaultPricingEngine
{
public async Task AddPrice(Product value)
{
var price = await _externalApi.GetPrice();
value.Prices.Add(price);
}
}

class Product
{
public int Id{get;set;}
public string Name {get;set;}
public List<decimal> Prices {get;set;}
}

如果我省略 GC.KeepAlive,它似乎会恢复到最初创建的产品。好像我保留它一样,价格按预期添加。

这里到底发生了什么导致清理.. GC.KeepAlive 是否真的发生了误报。

最佳答案

这与引用或垃圾收集无关。

您调用 AssignPrices,这是一个异步方法,无需等待它。这意味着您手上有竞争条件。

async 方法将在调用线程上同步运行,直到到达第一个 await 并且该方法返回控制权以及代表操作其余部分的任务。如果您不等待它(或同步阻止它),调用方法将与未等待的异步操作并行运行。

使用 GC.KeepAlive 只能通过延迟调用方法来实现,而 AssignPrices 有机会完成。

您应该等待操作,只有在操作完成后才能继续。您还应该向异步方法添加“Async”后缀,这有助于提醒您等待它。

public async Task CreateProductAsync(int id)
{
Product result = factory.Create(id);
await AssignPricesAsync(result);
Assert.That(result.Prices.Count == 1);
}

关于c# - 对象引用在多层异步等待操作中丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33306490/

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