I am looking for a simple and efficient way to asynchronously (wait / block) without having to poll within an Async Task
method.
I have created a simple psuedo-code situation below:
private var queue = new ConcurrentQueue<Command>();
// Function called by program
public async Task<String> GetNameAsync(int id)
{
//Build Command
var Command = new Command(id);
//Enqueue Command to concurrent queue
queue.enqueue(command);
//Wait for command to finnish executing, posibly supply a timeout
await command.CompleteCondition
//Once command has completed or timed out return the result of the task.
return command.Response.getString();
}
//Continiously runs in its own thread
private void MainThread()
{
while(mustRun)
{
if(queue.Any())
{
//Get command from queue if there is one
var command = queue.dequeue();
//Execute command
var result = ExecuteCcommand(command);
//Set Command Done with result (so the blocking async task can continue:
//TODO:
}else{
Thread.Sleep(100);
}
}
I have left out the mechanism which I do not know of, But essentially I need to pass some sort of lock along with the command to the main thread which will then notify the Async Task
once it has completed, so that the task can continue.
I am sure there must me some type of c# mechanism out there which is specifically designed to be used with the c# Async Task library. I am obviously not aware of it and have never worked with it. What would you recommend I use?
The simplest way would be to use a TaskCompletionSource
. For example:
public class Command
{
private readonly TaskCompletionSource<string> _tcs = new TaskCompletionSource<string>();
public Task<string> ExecuteAsync()
{
return _tcs.Task;
}
internal void ExecuteCommand()
{
if (_tcs.Task.IsCompleted) return;
try
{
// Do your work...
_tcs.SetResult(result);
}
catch (Exception ex)
{
_tcs.SetException(ex);
}
}
}
When executing the command, you just var result = await ExecuteAsync();
. In your worker, just do ExecuteCommand();
.