This is the model for 3 layer application with asynchronous response I am trying to use:
- GUI
- Back-end
- Remote Server
GUI:
private async void readFloatButton_Click(object sender, RoutedEventArgs e)
{
FloatValueLabel.Content = (await srvProtocol.ReadFloat("ReadFloatX")).ToString();
}
Back-end (uses internal variables binReader and connection)
public Task<float> ReadFloat(string cmd)
{
var tcs1 = new TaskCompletionSource<float>();
var floatTask = tcs1.Task;
RegisterResponse(cmd,
() =>
tcs1.SetResult(_binReader.ReadSingle());
);
// We are ready: now send request to server(assuming that this is a quick operation)
connection.Send(cmd);
return floatTask;
}
Here RegisterResponse adds a < Key, Action > pair to some thread-safe dictionary.
Another worker thread reads from the network stream messages (message headers) and calls actions according to the string cmd found in the message header.
Now the question:
- is it possible to reach same level of conciseness when I will need to subscribe GUI elements for periodic updates (not a single callback)?
Well, you could just take what you have and put in into a loop, e.g.:
Though I personally am not fond of the “infinite async” loop. The only way to stop the loop is to throw an exception (error or cancellation).
The Rx library is more suited for subscriptions. It allows a high level of
“conciseness,” but has a steeper learning curve.
You can also wrap all the subscription logic into a Model/ViewModel. This particularly makes sense when dealing with “updating” the same conceptual value. In that case,
StartReadingwould be a method on your Model/ViewModel. It would useasync(for the infinite async loop) orObserveOn(for Rx) to bring the updates onto the UI thread, and then use the standardINotifyPropertyChanged/ObservableCollectionto update the UI indirectly.