I have a pattern in my application where I would like to send out some command or start some IO work and wait for it to be completed, or have some mechanism to know if it has completed.
For this I plan to use the async
/await
pattern. I assume most people have come to the point in coding where they reach this pattern.
while(something)
DoNothing();
Where DoNothing()
usually ends up eating up some CPU time or just stopping the program altogether. I assume the proper way to get around this is with the async
/await
pattern.
In my case I have come up with the following simple method
public override async Task<Boolean> PerformProcessingAsync()
{
StartSomeIOProcessing();
while (TheIOProcessingResult == null)
await Task.Yield();
return true;
}
Which starts some IO processing and then waits for the result to be instantiated. In the meantime though it calls Task.Yield
to return to the calling context which can then continue work and also places a continuation of this method (the next while loop iteration) onto the call stack.
Is this the correct explanation, is this the correct way to fix the scenario described above?
EDIT: In a more specific situation that I am facing... I also maintain another library that performs IO work, basically reading and writing to SerialPort
objects. This library works by having a ConcurrentQueue
of reads or writes that it processes with respect to a specific port. A Task
"sits at the end" of this queue and consume the work as it goes.
Most reading work simply queries some value, parses it, and fires an event NewData(double myNewData)
which is listened to by the UI. In the UI a state representation is held of the SerialPort
s data. In the state representation the NewData
event is handled which updates the value of whatever it corresponds to.
Writing is done in the same manner but there is no event fired upon completion, the port is simply written to. The only way to tell if it was successful is to wait for the reads to update the state. (Sadly because of how the hardware acts there is no better way to do this).
My current application makes use of this library to perform its IO work. Reads are periodically sent to the library to keep the UI with fresh values from the ports... When a user clicks a button writes are sent off to the library to command something from the hardware.
I am in the situation where I want to assure that the write has happened programmatically. The only way I can think to do this is to send the write off to the library, and wait for the read to update the data the write effects.
Thus the loop.
I would extract the
StartSomethingIOProcessing
into a separateTask
that returns the result.Await
on that, then check the result.I believe you are misinterpreting the async/await operations. The await keyword is actually used to wait until the async operation finished so you don't need to implement a while loop anymore and check if it is null.
Yes, that likely is the only way to do it, but there are better ways than spin waiting to see if the read update happens.
Here is a example way to handle the processing like we talked in the chat we did. In summary, you have a queue of
IDataRequest
, in those request's they hold aTaskCompletionSource<T>
that represents the completion of sending the data. Once you do a request to the device and get a response you set the result of the completion source. I combined it with your existing event based implmentation, but honestly I would drop the event's and just have the callers do the update to the UI after awaiting the result ofRequestTemp()
.