Ask Learn
Preview
Ask Learn is an AI assistant that can answer questions, clarify concepts, and define terms using trusted Microsoft documentation.
Please sign in to use Ask Learn.
Sign inThis browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Did it occur to you that an infinite loop, with async/await inside it, isn't really an infinite loop? It looks like one (which is usually bad) but because of the asynchrony, we know that it isn't executing the entire method at one time. Part executes now, then sometime later it periodically resumes – that sounds kind of like a timer!
Let’s say I have some UI work I need to do on a periodic basis. Normally I have two options
The first option gives us code with clear intent (“loop and update forever!”), but it introduces multiple delegates, potential multithreading complexities depending on the work being done and we still have to get back onto the UI thread to update the UI.
void DoWorkPollingTask()
{
Task.Run(async () =>
{
while (true)
{
// do the work in the loop
string newData = DateTime.Now.ToLongTimeString();
// update the UI on the UI thread
Dispatcher.Invoke(() => txtTicks.Text = "TASK - " + newData);
// don't run again for at least 200 milliseconds
await Task.Delay(200);
}
});
}
whereas the second option, while keeping us on a single thread (the UI thread) spreads our intent across multiple methods because the "repeat" behavior is separate from the "work" behavior (i.e. the only way we know this is a periodic activity is that the method is named _timer_Tick) and may make for more difficult maintenance if it gets more complicated.
DispatcherTimer _timer = new DispatcherTimer();
void DoWorkTimer()
{
_timer.Interval = TimeSpan.FromMilliseconds(200);
_timer.Tick += _timer_Tick;
_timer.IsEnabled = true;
}
void _timer_Tick(object sender, EventArgs e)
{
// do the work in the loop
string newData = DateTime.Now.ToLongTimeString();
// update the UI on the UI thread
txtTicks.Text = "TIMER - " + newData;
}
There is a third option. Use an asynchronous loop. Even though this looks like an infinite loop, its really not. Because of the await of the delay Task, this method yields control back to the its caller periodically. If this weren’t an async method with a valid asynchronous operation, it would be a synchronous method and would deadlock the UI when we called it.
But since it is not, it works as needed and gives us both a very clear intent of what the code is supposed to do as well as keeps us on the UI thread the whole time (the magic of await!) so we don't have multithreaded issues or multiple delegates/callbacks.
private async Task DoWorkAsyncInfiniteLoop()
{
while (true)
{
// do the work in the loop
string newData = DateTime.Now.ToLongTimeString();
// update the UI
txtTicks.Text = "ASYNC LOOP - " + newData;
// don't run again for at least 200 milliseconds
await Task.Delay(200);
}
}
The real trick to making this work though, is not in the DoWorkAsyncInfiniteLoop method. Its how we call it. You do not await the call to it.
private void bttnStart_Click(object sender, RoutedEventArgs e)
{
// invoke loop method but DO NOT await it
DoWorkAsyncInfiniteLoop();
}
This will start the async loop but we do not want our code to await here for it to finish (because it won’t). We treat it as “fire and forget.”
This will also cause a green squiggle in Visual Studio because “Hey you forget to await this obviously async method!!!” We can ignore that, or just stash the returned task into a local variable so it doesn’t complain. What I will not do to “fix” the green squiggle is make the looping method return void instead of Task. Always return a Task, you never know who might want it in the future (maybe a future change also introduces a cancellation feature).
Other thoughts:
The above sample source is available on my GitHub.
Ask Learn is an AI assistant that can answer questions, clarify concepts, and define terms using trusted Microsoft documentation.
Please sign in to use Ask Learn.
Sign in