从异步功能列表中删除项目

问题描述 投票:0回答:1

我正在编写一个通过在列表中保留订阅ID的列表来删除所有订阅的功能。

我在遇到问题

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

因为在foreach循环中修改列表会引发错误。我在这个社区上发现我可以执行foreach(var subscriptions in _listOfSubscriptionIds.ToList()),但在空间复杂度方面听起来很糟糕,尤其是在订阅量约为1000万的情况下。

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

    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.我认为第二个在时间和空间复杂度上更好,但是我是对的吗?2.在第二种情况下,我是否可能会缺少比赛条件?3.在RemoveSubscription中,_listOfSubscriptionIds.Remove(subscriptionId)是否也在等待中,因为它处于异步功能中...?

c# linq lambda runtime race-condition
1个回答
0
投票

您的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);

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

© www.soinside.com 2019 - 2024. All rights reserved.