[解決済み] コレクションが変更されたため、列挙操作が実行されない可能性がある
質問
デバッガを付けるとこのエラーは発生しないようなので、真相が分かりません。
コレクションが変更されました。列挙操作が実行されない可能性があります。
以下はそのコードです。
WindowsサービスにおけるWCFサーバです。メソッド
NotifySubscribers()
は、データイベントがあるたびにサービスから呼び出されます(ランダムな間隔ですが、それほど頻繁ではなく、1日に約800回です)。
Windows Formsクライアントが購読すると、購読者IDが購読者辞書に追加され、クライアントが購読を解除すると、辞書から削除されます。このエラーは、クライアントが購読を中止したとき(または中止した後)に発生します。どうやら、次回以降に
NotifySubscribers()
メソッドが呼び出されると
foreach()
ループが失敗し、件名にエラーが表示されます。このメソッドは、以下のコードに示すように、アプリケーションログにエラーを書き込みます。デバッガが接続され、クライアントが配信を停止した場合、コードは正常に実行されます。
このコードに問題はないでしょうか?辞書をスレッドセーフにする必要があるのでしょうか?
[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);
}
}
}
解決方法は?
何が起こっているかというと
SignalData
は、ループの間にフードの下で間接的に購読者辞書を変更し、そのメッセージにつながるのです。 これを確認するには
foreach(Subscriber s in subscribers.Values)
への
foreach(Subscriber s in subscribers.Values.ToList())
私が正しければ、問題は解消される。
呼称
subscribers.Values.ToList()
の値をコピーします。
subscribers.Values
の先頭にある別のリストに追加します。
foreach
. このリストには他の誰もアクセスできないので(変数名さえない!)、ループの中では何も変更できない。
関連
-
[解決済み] エンティティタイプ ApplicationUser は、現在のコンテキストのモデルの一部ではありません。
-
[解決済み】非静的メソッドはターゲットを必要とする
-
[解決済み】クロススレッド操作が有効でない。作成されたスレッド以外のスレッドからアクセスされたコントロール
-
[解決済み] [Solved] アセンブリ System.Web.Extensions dll はどこにありますか?
-
[解決済み】Entity FrameworkからのSqlException - セッション内で他のスレッドが動作しているため、新しいトランザクションは許可されません。
-
[解決済み】HRESULTからの例外:0x800A03ECエラー
-
[解決済み】「...は'型'であり、与えられたコンテキストでは有効ではありません」を解決するにはどうすればよいですか?(C#)
-
[解決済み】IntPtrとは一体何なのか?
-
VSでscanfエラーを恒久的に解決するには、ソースファイルを作成し、自動的に#define _CRT_SECURE_NO_WARNINGS 1を追加してください。
-
[解決済み】別のスレッドがこのオブジェクトを所有しているため、呼び出し側のスレッドはこのオブジェクトにアクセスできない
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】ASP.NET Core Dependency Injectionのエラーです。アクティブ化しようとしているときに、タイプのサービスを解決できません。
-
[解決済み] DBNullから他の型にオブジェクトをキャストすることができない
-
[解決済み】Unity3DでOnTriggerEnterが動作しない件
-
[解決済み】非静的メソッドはターゲットを必要とする
-
[解決済み】MetadataException: 指定されたメタデータ・リソースをロードできない
-
[解決済み】Entity FrameworkからのSqlException - セッション内で他のスレッドが動作しているため、新しいトランザクションは許可されません。
-
[解決済み】C#のequal to演算子でtextとvarcharのデータ型は互換性がない
-
[解決済み】エラー「必要なフォーマルパラメータに対応する引数が与えられていない」を解決する?
-
[解決済み】Microsoft.Extensions.LoggingからILoggerを解決することができない
-
[解決済み】スレッド終了またはアプリケーションの要求により、I/O操作が中断されました。