21

いくつかの静的プロパティを持つ静的クラスがあります。それらすべてを静的コンストラクターで初期化しましたが、それは無駄であり、必要に応じて各プロパティを遅延ロードする必要があることに気付きました。そこで、このタイプを使用してすべてのダーティな作業を行うように切り替えSystem.Lazy<T>、私の場合、実行は常にシングルスレッドであったため、スレッドセーフ機能を使用しないように指示しました。

私は次のクラスに行き着きました:

public static class Queues
{
    private static readonly Lazy<Queue> g_Parser = new Lazy<Queue>(() => new Queue(Config.ParserQueueName), false);
    private static readonly Lazy<Queue> g_Distributor = new Lazy<Queue>(() => new Queue(Config.DistributorQueueName), false);
    private static readonly Lazy<Queue> g_ConsumerAdapter = new Lazy<Queue>(() => new Queue(Config.ConsumerAdaptorQueueName), false);

    public static Queue Parser { get { return g_Parser.Value; } }
    public static Queue Distributor { get { return g_Distributor.Value; } }
    public static Queue ConsumerAdapter { get { return g_ConsumerAdapter.Value; } }
}

デバッグしているときに、今まで見たことのないメッセージに気づきました。

関数の評価では、すべてのスレッドを実行する必要があります

ここに画像の説明を入力してください

を使用する前Lazy<T>は、値が直接表示されていました。次に、スレッドアイコンの付いた丸いボタンをクリックして、遅延値を評価する必要があります。.Valueこれは、のを取得している私のプロパティでのみ発生しますLazy<T>Lazy<T>実際のオブジェクトのデバッガビジュアライザーノードを展開すると、プロパティはメッセージなしでValue単に表示されます。null

そのメッセージは何を意味し、私の場合はなぜ表示されるのですか?

4

5 に答える 5

16

「方法:ウォッチの値を更新する」というタイトルのMSDNページを見つけました。

デバッガーで式を評価すると、2つの更新アイコンのいずれかが[値]列に表示される場合があります。1つの更新アイコンは、反対方向に円を描く2つの矢印を含む円です。もう1つは、糸に似た2本の波線を含む円です。

..。

2つのスレッドが表示される場合は、スレッド間の依存関係が存在する可能性があるため、式は評価されませんでした。クロススレッド依存関係とは、コードを評価するには、アプリケーション内の他のスレッドを一時的に実行する必要があることを意味します。ブレークモードの場合、通常、アプリケーションのすべてのスレッドが停止します。他のスレッドを一時的に実行できるようにすると、プログラムの状態に予期しない影響が生じ、デバッガーがブレークポイントなどのイベントを無視する可能性があります。

誰かがそれを与えることができれば、私はまだより良い説明が欲しいです。これで答えられない質問には、次のようなものがあります。すべてのスレッドを実行するには、どのような評価が必要ですか。デバッガーはどのようにしてそのようなケースを識別しますか?スレッド更新アイコンをクリックすると、正確にはどうなりますか?

編集:私はILSpyLazy<T>の下で調べたときに答えに出くわしたと思います(まったく異なる理由で)。プロパティのゲッターには、への呼び出しがあります。MSDNには次のように書かれています。ValueDebugger.NotifyOfCrossThreadDependency()

[...]関数評価を実行するには、通常、評価を実行しているスレッドを除くすべてのスレッドをフリーズする必要があります。リモーティングシナリオで発生する可能性があるように、関数評価で複数のスレッドでの実行が必要な場合、評価はブロックされます。NotifyOfCrossThreadDependency通知は、スレッドを解放するか、関数の評価を中止する必要があることをデバッガーに通知します。

したがって、基本的に、式を評価しようとしてVisual Studioが30秒間ハングし、「関数の評価がタイムアウトした」と通知するという厄介なケースを防ぐために、コードはデバッガーにフリーズを解除する必要があることを通知する機会があります。評価が成功するか、そうでなければ評価が永久にブロックされる他のスレッド。

他のスレッドを実行するとデバッグセッションが中断する可能性があるため、通常、式を評価するときに他のすべてのスレッドがフリーズしたままになるため、デバッガーは自動的に処理されず、うさぎの穴を飛び降りる前に警告します。

于 2010-12-16T12:49:13.033 に答える
3

私の推測では、デバッガーはプロパティをロードすることでアプリケーションの状態に影響を与えないようにしようとしていると思います。

遅延読み込みは、プロパティを参照/アクセスするときにのみ発生することを覚えておく必要があります。

さて、一般的に、デバッグがアプリケーションの状態に影響を与えることは望ましくありません。そうしないと、アプリケーションの状態がどうあるべきかを正確に表すことができません(マルチスレッドアプリケーションとデバッグを考えてください) 。

特異なバグを見てください

于 2010-12-16T11:26:43.483 に答える
3

私はこれに何時間も苦労し、すべてのスレッドに誤解を招くような実行を要求することに関する元のエラーメッセージを見つけました。新しいソリューションから既存のデータベースにアクセスし、新しいソリューション内に新しいEntity FrameworkエンティティPOCOとデータアクセスレイヤーを作成して、にアクセスしてマッピングしていましたDB

私は最初に2つのことを間違えました。POCOC#エンティティで主キーを適切に定義していませんでした。tableアクセスしていたDB(ではdbo.tablenameなくedi.tablename)に一意のスキーマがありました。

私のDbContext.csファイルでは、正しいスキーマの下にテーブルをマップするために次のことを行いました。これらを修正すると、エラーはなくなり、問題なく機能しました。

protected override void OnModelCreating(DbModelBuilder dbModelBuilder)
{
    base.OnModelCreating(dbModelBuilder);
    dbModelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    dbModelBuilder.Entity<TableName>().ToTable("TableName", schemaName: "EDI");
}
于 2018-02-16T20:11:45.853 に答える
0

ローカル変数を作成し、検査する値を割り当てます。

これにより、デバッガーはプロパティにアクセスすることでアプリケーションが妨害されるかどうかを心配する必要がないため、ローカル変数に割り当てるときに既にアクセスされているため、検査できます。

于 2015-11-12T17:20:44.813 に答える
0

私にとっては、DBContextに行があるかどうかに関係なく、this.Configuration.LazyLoadingEnabled = false;またはを持っているかどうかは問題ではないことがわかりました。= true;問題を読んだところ、スレッドが発生していて、デバッガーがスレッドを実行する許可を求めているか、スレッドが起動する前に警告を発しているために発生しているようです。明らかに、場合によっては、MUG4Nの回答に従って続行することもできます: デバッグ中のVisual Studio:関数の評価では、すべてのスレッドを実行する必要があります

しかし、私が見つけたのは、問題を回避できるということでした。

2つのオプション:

  1. .ToList()あなたの追加Queues

    var q = db.Queues.OrderBy(e => e.Distributor).ToList();

  2. 非公開メンバー>_internalQuery>ObjectQuery>結果ビューを選択することで回避策を見つけました。

ここに画像の説明を入力してください

于 2018-09-05T21:32:27.480 に答える