[解決済み】コレクションが変更され、列挙操作が実行されないことがある。
質問
コードは次のとおりです。
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class SubscriptionServer : ISubscriptionServer
{
private static IDictionary<Guid, Subscriber> subscribers;
public SubscriptionServer()
{
subscribers = new Dictionary<Guid, Subscriber>();
}
public void NotifySubscribers(DataRecord sr)
{
foreach(Subscriber s in subscribers.Values)
{
try
{
s.Callback.SignalData(sr);
}
catch (Exception e)
{
DCS.WriteToApplicationLog(e.Message,
System.Diagnostics.EventLogEntryType.Error);
UnsubscribeEvent(s.ClientId);
}
}
}
public Guid SubscribeEvent(string clientDescription)
{
Subscriber subscriber = new Subscriber();
subscriber.Callback = OperationContext.Current.
GetCallbackChannel<IDCSCallback>();
subscribers.Add(subscriber.ClientId, subscriber);
return subscriber.ClientId;
}
public void UnsubscribeEvent(Guid clientId)
{
try
{
subscribers.Remove(clientId);
}
catch(Exception e)
{
System.Diagnostics.Debug.WriteLine("Unsubscribe Error " +
e.Message);
}
}
}
実行すると、エラーが発生します。
Collection was modified; enumeration operation may not execute
しかし、デバッガを付けてもエラーは出ませんし、問題の所在が分かりません。
Windowsサービス内のWCFサーバです。メソッド
NotifySubscribers()
は、データイベントがあるたびにサービスから呼び出されます(ランダムな間隔ですが、それほど頻繁ではなく、1日に約800回です)。
Windows Formsクライアントが購読すると、購読者IDが購読者辞書に追加され、クライアントが購読を解除すると、辞書から削除されます。このエラーは、クライアントが購読を中止したとき(または中止した後)に発生します。どうやら、次回以降に
NotifySubscribers()
メソッドが呼び出されると
foreach()
ループが失敗し、件名にエラーが表示されます。このメソッドは、以下のコードに示すように、アプリケーションログにエラーを書き込みます。デバッガが接続され、クライアントが配信を停止した場合、コードは正常に実行されます。
解決方法は?
何が起こっているかというと
SignalData
は、ループの間にフードの下で間接的に購読者辞書を変更し、そのメッセージにつながるのです。これを確認するには
foreach(Subscriber s in subscribers.Values)
への
foreach(Subscriber s in subscribers.Values.ToList())
私が正しければ、問題は解消される。
呼称
subscribers.Values.ToList()
の値をコピーします。
subscribers.Values
の先頭にある別のリストに追加します。
foreach
. このリストには他の誰もアクセスできないので(変数名さえない!)、ループの中では何も変更できない。
関連
-
batスクリプトからログを出力する方法
-
git eclipseプラグインのインストール
-
linux シェル学習ノート 2日目
-
[解決済み】C++使用時、代入の左オペランドにlvalueが必要なエラーについて
-
[解決済み】入力文字列のフォーマットが正しくない
-
[解決済み】「Error: デフォルトのデータセット例mtcarsとggplot2における「離散的なスケールに連続的な値が供給された」。
-
[解決済み] 'push_back' の呼び出しに対応するメンバ関数がないエラー
-
[解決済み】二重の空きや破損(fasttop)
-
[解決済み】C#でクエスチョンマークを2つ並べるとどんな意味になるのか?
-
[解決済み】クロススレッド操作が有効でない。作成されたスレッド以外のスレッドからアクセスされたコントロール
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Swift言語とAppleScriptの違い、AppleScriptの開発状況について教えてください。
-
合理的オブジェクトスクリプトコマンド
-
[解決済み】R: predict() で数値 'envir' 引数が長さ1でない。)
-
[解決済み】C++使用時、代入の左オペランドにlvalueが必要なエラーについて
-
[解決済み】Jupyter Notebookが保存されない:postに'_xsrf'引数がない
-
[解決済み】C++ Cout & Cin & System "Ambiguous" [クローズド]。
-
[解決済み】 lm.fit(x, y, offset = offset, singular.ok = singular.ok, ...) でエラー : 'y' に NA/NaN/Inf, あらゆる方法を試したが解決しなかった。
-
[解決済み] 'push_back' の呼び出しに対応するメンバ関数がないエラー
-
[解決済み】行列式で「数値/複雑な行列/ベクトルの引数が必要です」というエラーが発生?
-
[解決済み】count()パラメータは配列かlaravelのcountableを実装したオブジェクトでなければならない。