Question

I want to be able to run another global method which will continue execution while the user navigates through the pages.

So I made a task in App.xaml:

public static Task globalTask = null;

and then:

public App()
{
    ...
    globalTask = Update();
}

and Update() method is this:

public async Task Update()
{
    while (true)
    {
        if (DateTime.Now.Second % 5 == 0)
            await db.InsertCurrentTime(DateTime.Now);
    }
}

but when I debug, I see that Update() isn't working continuously.

the question is: How can I make the Update() method just continue working while the app is running? No matter, with async await or in another way.

Note: this is a simplified version of what I'm doing, unnecessary things removed

Was it helpful?

Solution

So there are several issues here.

First, an async method simply allows the use of await within the method. It doesn't automatically make the method run in another thread. When this method is called the caller will run the method synchronously until it hits an await and then run the rest of the method as a continuation of the awaited task. Since you have no await, and you have an infinite loop, it means that calling this method just results in the caller blocking forever.

Next, your code seems to be intended to run some code once every 5 seconds, but it doesn't do that. Instead, it runs the given block of code as many times as it possibly can in one out of every five seconds. Now it seems that the operation is inserting something into a database, which it may well be able to do a few times per second. If you had a faster operation it may well be able to do it millions of times in a single second. That's probably bad. You don't want to do that.

Oh, and it also has the problem that it's possible for the thread to go an entire second without ever being scheduled. One would hope that it wouldn't be happening in general, as that's a long time for a computer, but it is technically possible for an entire iteration to be skipped.

Another problem is that you're doing a busy wait. In 4 out of 5 seconds your code is sitting there spinning around in its while loop as fast as it possibly can, skipping the if block each time. This is wasting tons and tons of CPU time for literally zero benefit.

So while you may be able to find a way of moving this to another thread, you don't want to do that. Instead, just use a Timer and set the interval to 5 seconds to run some code every 5 seconds reliably and efficiently.

If you want to use await, then you can do something like this:

public async Task Update()
{
    while (true)
    {
        db.InsertCurrentTime(DateTime.Now);
        await Task.Delay(TimeSpan.FromSeconds(5))
            .ConfigureAwait(false);//remove if you want the UI context
    }
}

This then ensures that you are running the block of code once every 5 seconds, and that you're not performing a busy wait for those 5 seconds but rather making the method properly asynchronous and having each iteration of the loop schedule a continuation to run in 5 seconds.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top