我正在编写一个通过在列表中保留订阅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)
是否也在等待中,因为它处于异步功能中...?
您的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);
进行反向迭代可确保特定索引处的值在循环期间不会更改。