Reputation: 8780
I'm integrating with a PIN device with an api containing asynchronous methods. For example one of them is called GetStatus and it raises a DeviceStateChangedEvent with the state passed into it as a parameter.
I'd like to have an interface that is not asynchronous over it though, so that when I call GetStatus on my interface it will actually return the status rather than raising an event to pass that data to me.
I'm thinking I could do something like this:
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;
}
}
Is this a good way to address this or this there a better solution?
Upvotes: 1
Views: 1272
Reputation: 54877
What you’re doing in your example is called “busy-waiting” (or “spinning”), which is unrecommended in most scenarios since it wastes a lot of CPU power. Preferably, you should use a signalling mechanism, such as the WaitHandle
class, for synchronizing when an event of interest (in your case, StatusChangedEvent
) has occurred:
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
}
}
Upvotes: 5
Reputation: 1062600
The best option: code it async.
No; that is a hot loop. It will hammer the CPU. It also isn't guaranteed to exit due to register caching (this is trivial to demonstrate on x86 in particular).
If you need it sync, you should use something like an AutoResetEvent
.
Upvotes: 2