2012-02-20 2 views
1

비동기 메서드가 포함 된 API로 PIN 장치와 통합됩니다. 예를 들어 이들 중 하나는 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

합니다. 기다릴 수 있니? –

+0

'DeviceStateChangedEvent' 이벤트는'GetStatus'에 대한 호출과 동기화되어 있습니까? 좀 더 명확하게,이 이벤트의 가능한 순서 :'GetStatus','GetStatus','DeviceStateChangedEvent','DeviceStateChangedEvent' –

답변

4

예제에서 수행하는 작업은 "busy-waiting"(또는 "회전")이라고 불리는데, 이는 대부분의 시나리오에서 권장하지 않는 것이므로 많은 CPU 전력을 낭비합니다. 바람직하게는, 당신은 (귀하의 경우, StatusChangedEvent) 관련 이벤트가 발생한 경우 동기화, 같은 WaitHandle 클래스로, 신호 전달 메커니즘을 사용한다 : 그들은 이유가 비동기있어

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

마크, 동기 장치에서 작동하는 인터페이스를 만들지 않았 으면 좋겠다. 비동기식 장치. 비동기 적으로 동작하기 위해이 장치가 필요하지는 않습니다. 따라서 인터페이스를 동기식으로 만들고 코드를 간소화하는 것이 이점이라고 생각합니다. AutoResetEvent 팁을 보내 주셔서 감사합니다. –

+0

참고로, 나는 실제로 신용 카드 제공 업체와의 인터페이스를 통해 다른 방향으로 나아갔습니다. PC Charge는 동기식이었고 PPI는 아니기 때문에 어떤 코드를 사용 하던지 상관없이 소비 코드에 비동기적인 인터페이스를 만들었습니다. 돌이켜 보았을 때 그것은 합당하지 않은 이유로 통합하고 유지하기가 더 어려워 졌기 때문에 실수였습니다. –

+0

@BrandonMoore는 AutoResetEvent 또는 (신호로 Pulse/Wait을 사용하는 것에 익숙한 경우)'Monitor'를 사용합니다. –

관련 문제