2009-04-20 8 views
0

私はいくつかの行を持っていますが、これらの実行中に他のスレッドへのコンテキスト切り替えがないことを確認したいのですが?はい、再設計はオプションですが、これを行うことができれば、現在のところはるかに便利です。C#でコンテキストスイッチなしでアトミック操作を強制する方法はありますか?

これは可能ですか?そうでなければ誰もが決定の背後にある推論を知っていますか?

編集:のGetValue()が呼び出されたときに私が求めていた理由は、私は値を返す責任クラスを持っているということです、値はイベントを介して提供されるので、スレッドはイベントが発生するまでブロックする必要があります。私はこのためのテストを書くことを考えることができ

public class ValueResolver { 
    IPersistentNotifier _notifier; 
    IValueMonitor _monitor; 
    Value _value; 
    ManualResetEvent _resolvedEvent = new ManualResetEvent(false); 
    public ValueResolver(IPersistentNotifier notifier, IValueMonitor monitor) { 
    _notifier = notifier; 
    _monitor = monitor; 
    _monitor.ValueAcquired += ValueAcquired; 
    } 
    public Value GetValue() { 
    _value = null; 
    persistentNotifier.Show("Getting Value") 
    _monitor.Start(); 
    _resolvedEvent.WaitOne(60000, false); 
    return _value 
    } 
    public void ValueAcquired(Value val) { 
    _value = val; 
    _monitor.Stop(); 
    _notifier.Hide(); 
    _resolvedEvent.Set(); 
    } 
} 

唯一の方法は、(Rhinoのモック中)

var monitor = MockRepository.GetMock<IValueMonitor>() 
monitor.Expect(x=>x.Start()).Do(new Action(() => { 
    Thread.Sleep(100); 
    monitor.Raise(y=>y.ValueAcquired, GetTestValue()); 
}); 

のようなものですが、何か提案は歓迎されています。だから我々は持っています。

+0

コンストラクタの署名に誤字はありますか?私は抽象型IPersistentNotifierがPersistentNotifierではなく(IPersistentNotifierの証明であると仮定して)渡されると考えていたでしょう。 –

+0

はい、コピー貼りスキルの欠如によるタイプミス –

答えて

9

いいえ、できません。ロックを使用して、他のスレッドが操作に関連する重要なコードを入力しないようにすることができますが、それだけです。

"理由"については、一般的には必要ではなく、相対的に高いレベルのプラットフォーム上の先制型オペレーティングシステムでは少し奇妙です。ドライバコードでは可能かもしれませんが、通常はユーザコードでは必要ありません。

マルチコアマシンとマルチプロセッサマシンでは、「実行中の他のスレッド」は必ずしもコンテキスト切り替えを意味するとは限りません。

編集:あなたの編集にもかかわらず、私はまだそれがコンテキストスイッチであることが問題であるとは思わない。スレッドがとにかくブロックしなければならない場合は、になり、別のスレッドへのコンテキスト切り替えになります。私はあなたのテストがあなたが必要とする他のスレッドですべてが起きるようになると確信するために100msほど待たなければならないことを少し迷っていることに同意するが、間違いなくがそれを保証する必要があるコンテキストスイッチは行われません。

+0

_monitor.Start()とWaitAndSet命令を実行している間に発生するイベントが心配です –

+0

これは、起こらない。代わりに、通常のMonitorクラスとMonitor.Pulse/Waitを使用できますか?そうすれば、そんなことを避けることが容易になります。 –

4

コンテキストスイッチは、OSがシステム内で実行中のすべてのスレッド\プロセスに対して「公平」になるようにする方法です。 OS(Windowsなど)に基づいて、優先度に基づいたプリエンプティブスケジューリングが実装されています。プリエンプティブスケジューリングとは、優先度の高いスレッドが実行可能な状態であれば、現在のスレッドがCPUを離れなければならないことを意味します。

アトミックコードを書くとは、OSが許可しないOSのスケジューリングを中断するという意味です。また、Windowsイベント駆動型のスケジューリング。同じ優先順位の待機中のスレッドがない限り、CPUを保持することはできません。

+0

うーん、それは私が思ったことのようなものなので、私の単体テストはやや脆くなるかもしれません... –

+0

あなたのユニットテストは、コンテキスト切り替えではないスレッドに頼るのはなぜですか? –

+0

私がこれをやっている理由を編集を参照してください –

2

Windowsおよび他のすべての最新のOSは、プリエンプティブにスケジュールされたマルチプロセッシングOSです。 OSは個々のプロセスにタイムスライスを割り当てることを担当しており、個々のプロセスがシステムに影響を与えることはできません。

あなたのコードがあなたの魔法の "no context switches"コードセクションの中で無限ループに入ったとします。システム全体がフリーズし、再起動する必要があります。

0

なぜイベントが発生するのですか? (IValueMonitor)のメソッドで値を取得することはできませんか?

おそらく私は理解していません...

+0

私の場合、IValueMonitorは定期的にサービスをチェックして、そのサービスから返された値が特定のしきい値を超えているかどうかを確認します。 スケール上のオブジェクトの重みをとるアプリケーションを考えてみましょう。アプリケーションの適切なポイントでは、「位取りオブジェクトをスケールで」メッセージを表示して停止し、スケールのウェイトプロバイダを監視して、ウェイトスレッシュホールドが現在の値を超えていないかどうかを確認します。それだけがそれを続けます(またはタイムアウトまたはアボート時に)。 –

関連する問題