Throw timeout exception but action should be completed in background
When looking at your wrapper solution you wait on the task to complete with a timeout. First you do not need WaitAny
here. You can basically use Task.Wait(timeout)
. Secondly Task.WhenAll
is not needed for the task to continue in the background so this should be sufficent:
var taskToRun = Task.Factory.StartNew(() => GetCustomEntity());
if (!taskToRun.Wait(TimeSpan.FromMilliseconds(timeout)))
{
throw new TimeoutException();
// taskToRun will continue its execution in the background
}
Keep in mind that .Wait
or .WaitAny
will block the current thread from execution and could lead to race conditions! If you want to use async/await
to avoit that you could use Task.WhenAny
:
var taskToRun = Task.Factory.StartNew(() => GetCustomEntity());
var completedTask = await Task.WhenAny(taskToRun, Task.Delay(timeout));
if (completedTask == taskToRun)
{
// No Timeout
}
else
{
// Timeout
throw new TimeoutException();
}
if you want to return the value if the request finished in time you could then do s.th. like this:
var taskToRun = Task.Factory.StartNew(() => GetCustomEntity());
var completedTask = await Task.WhenAny(taskToRun, Task.Delay(timeout));
if (completedTask == taskToRun)
{
// No Timeout
return await completedTask;
}
else
{
// Timeout
throw new TimeoutException();
}
or with the wait approach:
var taskToRun = Task.Factory.StartNew(() => GetCustomEntity());
if (!taskToRun.Wait(TimeSpan.FromMilliseconds(timeout)))
{
throw new TimeoutException();
// taskToRun will continue its execution in the background
}
else
{
return taskToRun.Result;
}