I have a code that looks like this:
public static async Task<Request> SendRequest(Client client, DateTime startTime, int offset)
{
TimeSpan timeToWait = startTime - DateTime.UtcNow + TimeSpan.FromMilliseconds(offset);
await Task.Delay(timeToWait);
Console.Write(offset);
Request request = client.sendRequest();
}
async static public Task<Request> SendMultiple(Client client, DateTime startTime)
{
var offsets = new[] { -15, -10 };
offsets.ForEach(offset => tasks.Add(SendRequest(client, startTime, offset));
Request[] result = await Task.WhenAll(tasks);
}
The problem it seems, is that the prints show that:
08:59:59,985: -15
09:00:00,015: -10
So the first try was indeed, 15 milliseconds before 9AM. However, the second tried 15 milliseconds after 9AM instead of 10 milliseconds prior.
How could I ensure that those requests are being send exactly at the time I want, please?
I am using Ubuntu*
2
Answers
Looks like the issue might be related on how you are calculating the time delay for each request.
I calculate the current time before calculating the time to wait. Check if the calculated time to wait is negative, meaning that the start time has already passed. In such cases, I don’t delay and proceed immediately. Using a
List<Task<Request>>
to collect the tasks for each request and then awaitTask.WhenAll
to wait for all requests to complete.output:
I think that your best bet is to wait with a timer (
Task.Delay
) until a few milliseconds before the target time, and then wait the final milliseconds by spinning. In the example below the spinning duration is set to about 20 milliseconds:Spinning consumes a physical CPU thread, so you should avoid spinning on more threads than the number of physical CPU cores of your machine. A more sophisticated approach would be to dedicate just one thread for spinning, which would control other worker threads by signaling
ManualResetEventSlim
components.