[英]Removing items from list in an async function
我正在編寫 function 以通過在列表中保留訂閱 ID 列表來刪除所有訂閱。
我遇到了問題
foreach (var subscriptionId in _listOfSubscriptionIds)
{
await _hubProxy.Invoke("removeSubscription", subscriptionId);
_listOfSubscriptionIds.Remove(subscriptionId);
}
因為在 foreach 循環中修改列表會引發錯誤。 我在這個社區發現我可以做foreach(var subscriptions in _listOfSubscriptionIds.ToList())
但這在空間復雜度方面聽起來很糟糕,特別是如果有大約 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));
}
一些問題:
我認為第二個在空間和時間復雜度方面更好,但我是對的嗎?
在第二種情況下,我可能會丟失一個可能的競爭條件嗎?
在 RemoveSubscription 中,是否也等待_listOfSubscriptionIds.Remove(subscriptionId)
因為它處於異步 function...?
編輯:我沒有分享的一個細節使得調用_listOfSubscriptionIds.Clear()
或迭代_listOfSubscriptionIds
有問題的是_hubProxy
上可能有多個客戶端,每個客戶端都有其獨特的訂閱集。
具有訂閱 ID {a, b, c, d, e} 的客戶端 1
具有子 ID {f, g, h, I, j, k} 的客戶端 2
具有子 ID、{l、m、n、o、p} 等的客戶端 3。
這意味着當我調用 client1.RemoveAllSubscriptions() 時,它也可能會清除 client2、client3 等的訂閱 ID。
您的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);
反向迭代確保特定索引處的值在循環期間不會改變。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.