We have a logic for a background job to keep running, either every 20 minuts, or when a task if finished.
A simplified version of what I want to do is as followed:
Task to control if we need to exit:
private static TaskCompletionSource<bool> forceSyncTask = new TaskCompletionSource<bool>();
Background job:
Task.Factory.StartNew(
async () =>
{
do
{
await Dosomething();
await Task.WhenAny(Task.Delay(TimeSpan.FromMinutes(20)), forceSyncTask.Task);
// Always reset the force sync property
forceSyncTask = new TaskCompletionSource<bool>();
}
while (true);
});
Then everytime there is a notification comes, I run the following to force to exit the Task.WhenAny
if (!forceSyncTask.Task.IsCompleted)
{
forceSyncTask.TrySetResult(true);
}
I tested it in dev box and it works. However after I deployed it to our webervice in prod environment, even if I successfully SetResult (I have logging to know if TrySetResult returns true or not), the Task.WhenAny does not exit as expected.
Anyone has any idea why?
First, I recommend you use an established solution for pausing asynchronous methods, such as Stephen Toub's PauseToken
or the PauseToken
from my AsyncEx library . There's some red flags in the code as it currently stands: StartNew
with an async
delegate and without a TaskScheduler
, and TaskCompletionSource<T>
being used without the RunContinuationsAsynchronously
option. It's better to stick to higher-level constructs ( Task.Run
and PauseToken
, respectively) because there are lots of sharp corners on the low-level constructs.
As far as what exactly the problem is, that's difficult to tell, especially since you (and we) cannot reproduce it locally. Here's my top guesses:
TrySetResult
ends up directly invoking some code within Task.WhenAny
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.