Помещение синхронной оболочки поверх асинхронных методов - PullRequest
1 голос
/ 21 февраля 2012

Я интегрируюсь с устройством PIN с API, содержащим асинхронные методы. Например, один из них называется 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;
    }
}

Является ли это хорошим способом решения того или иного там лучшего решения?

Ответы [ 2 ]

5 голосов
/ 21 февраля 2012

То, что вы делаете в своем примере, называется « занят-ожидание » (или «вращение»), что не рекомендуется в большинстве сценариев, так как расходует много ресурсов процессора. Желательно, чтобы вы использовали механизм сигнализации, такой как класс WaitHandle, для синхронизации, когда произошло интересующее вас событие (в вашем случае StatusChangedEvent):

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
    }
}
2 голосов
/ 21 февраля 2012

Лучший вариант: закодировать его асинхронно.

Нет;это горячая петля.Это забьет процессор.Также не гарантируется выход из-за кэширования регистра (это тривиально для демонстрации, в частности, на x86).

Если вам нужна синхронизация, вы должны использовать что-то вроде AutoResetEvent.

...