2012-02-20 4 views
1

私は非同期メソッドを含むAPIを持つPINデバイスと統合しています。たとえば、それらのうちの1つはGetStatusと呼ばれ、DeviceStateChangedEventを渡した状態をパラメータとして送出します。同期ラッパーを非同期メソッドに置く

私はインターフェイス上でGetStatusを呼び出すと、そのデータを渡すためにイベントを発生させるのではなく、実際にステータスを返すように、非同期ではないインターフェイスを使用したいと考えています。

public class MSRDevice 
{ 
    StatusInfo _status; 
    bool _stateChangedEventCompleted = false; 
    IPAD _ipad; // <-- the device 

    public MSRDevice() 
    { 
     //Initialize device, wire up events, etc. 
    } 

    public StatusInfo GetStatus() 
    { 
     _ipad.GetStatus() // <- raises StatusChangedEvent 
     while(!_stateChangedEventCompleted); 
     _stateChangedEventCompleted = false; 
     return _status; 
    } 

    void StateChangedEvent(object sender, DeviceStateChangeEventArgs e) 
    { 
     _status = e.StatusInfo; 
    } 
} 

が、これはそこよりよい解決策を、このまたはこれに対処するための良い方法です:

私はこのような何かを行うことができます思ってい?

+0

を彼らが理由で非同期です:。好ましくは、あなたは(あなたのケースでは、StatusChangedEvent)該当するイベントが発生した際に同期させるために、このようWaitHandleクラスとして、シグナリングメカニズムを使用する必要があります待つことができますか? –

+0

'DeviceStateChangedEvent'イベントは' GetStatus'の呼び出しに関して同期していますか?明らかに、これはイベントの可能なシーケンスです: 'GetStatus'、' GetStatus'、 'DeviceStateChangedEvent'、' DeviceStateChangedEvent' –

答えて

4

あなたの例でやっていることは、多くのCPUパワーを無駄にするので、ほとんどのシナリオでは推奨されていない "busy-waiting"(または "スピニング")と呼ばれています。

public class MSRDevice 
{ 
    StatusInfo _status; 
    IPAD _ipad; // <-- the device 

    private EventWaitHandle waitHandle = new AutoResetEvent(false); 

    public MSRDevice() 
    { 
     //Initialize device, wire up events, etc. 
    } 

    public StatusInfo GetStatus() 
    { 
     _ipad.GetStatus() // <- raises StatusChangedEvent asynchronously 
     waitHandle.WaitOne(); // <- waits for signal 
     return _status; 
    } 

    void StateChangedEvent(object sender, DeviceStateChangeEventArgs e) 
    { 
     _status = e.StatusInfo; 
     waitHandle.Set(); // <- sets signal 
    } 
} 
+0

whileループは、方法はあった。例を書いてくれてありがとう! –

2

最適なオプション:非同期です。

いいえ;それはホットループです。それはCPUを叩くでしょう。また、レジスタキャッシングのために終了することも保証されていません(これは特にx86でのデモンストレーションです)。

同期が必要な場合は、AutoResetEventのようなものを使用する必要があります。

+0

Marc、私が同期デバイスのために働いていたインターフェースを作ろうとしなかったら非同期デバイス。私たちがこのデバイスを非同期的に動作させるために必要な理由はまったくありませんので、インターフェイスを同期させてコードを単純化することが利益となります。 AutoResetEventのおかげでありがとう、私はそれをチェックします。 –

+0

参考までに、私は実際には、クレジットカード会社へのインターフェースを使ってそれを逆にしました。 PCチャージは同期していたので、PPIは使用されていなかったので、使用されたコードに関係なく、消費コードに非同期に見えるインターフェースを作成しました。振り返ってみると、正当な理由がなくても、統合と保守が難しくなったため、間違いでした。 –

+0

@BrandonMooreは、AutoResetEventまたは(信号としてPulse/Waitを使い慣れている場合) 'Monitor'のいずれかを使用します。 –

関連する問題