从异步函数中的列表中删除项目

Removing items from list in an async function

我正在编写一个函数,通过在列表中保留订阅 ID 列表来删除所有订阅。

我遇到了

的问题
     foreach (var subscriptionId in _listOfSubscriptionIds)
     {
           await _hubProxy.Invoke("removeSubscription", subscriptionId);
           _listOfSubscriptionIds.Remove(subscriptionId);
     }

因为在 foreach 循环中修改列表会引发错误。我在这个社区发现我可以做 foreach(var subscriptions in _listOfSubscriptionIds.ToList()),但就 space 的复杂性而言,这听起来很糟糕,尤其是在有大约 10000000 个订阅的情况下。

所以我将其更改为以下内容:

    public async Task RemoveSubscription (string subscriptionId)
    {
        await _hubProxy.Invoke("removeSubscription", subscriptionId);
        _listOfSubscriptionIds.Remove(subscriptionId);
    }
    public void RemoveAllSubscriptions()
    {
        _listOfSubscriptionIds.ForEach(async subscriptionId => await RemoveSubscription(subscriptionId));
    }

一些问题:

  1. 我认为第二个在 space 和时间复杂度方面更好,但我是对的吗?

  2. 在第二种情况下是否存在我可能遗漏的竞争条件?

  3. 在 RemoveSubscription 中,_listOfSubscriptionIds.Remove(subscriptionId) 是否也在等待,因为它在异步函数中...?

编辑:我没有分享的一个细节导致调用 _listOfSubscriptionIds.Clear() 或遍历 _listOfSubscriptionIds 出现问题,即 _hubProxy 上可能有多个客户端,每个客户端都有他们独特的订阅集。

订阅 ID 为 {a, b, c, d, e} 的客户端 1

具有 subIds {f, g, h, I, j, k} 的客户端 2

具有 subIds 的客户端 3,{l, m, n, o, p} 等

这意味着当我调用 client1.RemoveAllSubscriptions() 时,它可能也会清除 client2、client3 等的 subscriptionId。

您的 ForEach 本质上是即发即弃;它不能确保所有任务 运行 完成。

您最好反向使用 for 循环,并保留任务以便等待它们:

var tasks = new List<Task>();
for (int i = _listOfSubscriptionIds.Count - 1; i >= 0; i--)
{
    tasks.Add(RemoveSubscription(_listOfSubscriptionIds[i]));
}

await Task.WhenAll(tasks);

反向迭代确保特定索引处的值在循环期间不会改变。