I understand how I can await
on library code to wait for a network request or other long-running action to complete, but how can I await
on my own long-running action without busy waiting?
This is the busy-waiting solution. How can I make it event-driven?
public async Task<DataBlock> ClickSend() {
// await until someone calls DataReceived()
while (_Block == null) {
await Task.Yield();
}
return _Block;
}
// Something external calls this function.
// Once called, ClickSend should complete with this data.
public void DataReceived(DataBlock data_block) {
_Block = data_block;
}
DataBlock _Block = null;
(This question is completely different from How do I await events in C#? which is asking how to await on event handlers, but very similar to Promise equivalent in C#.)
Generally in concurrency a "future" is placeholder for a return value and it has an associated "promise" that is fulfilled to pass the final return value.
In C#, they have different names: the future is a Task and the promise is a TaskCompletionSource.
You can create a promise, await on it, and then fulfill it when you get your callback:
TaskCompletionSource<DataBlock> _Promise = new TaskCompletionSource<DataBlock>();
public async Task<DataBlock> ClickSend() {
DataBlock block = await _Promise.Task;
return block;
}
public void DataReceived(DataBlock data_block) {
_Promise.TrySetResult(data_block);
}