The Thread
constructor does not understand async
delegates. You can read about this here:
The "proper" way to execute periodically some code depends on where you want to run your code. Do you have any reason to run it on a dedicated thread? Some components are thread-affine, and require to be manipulated by the same thread for the entirety of their existence. If you have this (not very common) requirement, you can use the Thread
constructor without async/await:
var myThread = new Thread(() =>
{
while (true)
{
var delayTask = Task.Delay(1000);
CPU_Load();
delayTask.Wait();
}
});
myThread.IsBackground = true;
myThread.Start();
Notice how the Task.Delay
task is created before the CPU-bound operation, and then waited afterwards. This way the interval between two subsequent invocations of the CPU_Load
method will be constant. It will not depend on the duration of the call itself.
If you don't need a dedicated thread, you can do the work more economically by using reusable threads from the ThreadPool
. Which is exactly what your current MyTask
implementation does, with the Task.Run
method inside. To start the task is as easy as invoking the asynchronous method:
var myTask = MyTask();
Now the task is running, and will continue running until the process terminates, or the CPU_Load
invocation fails, whatever comes first.
Another way to implement the asynchronous MyTask
method would be to wrap the whole loop in a Task.Run
, instead of having the Task.Run
inside the loop. Functionally and performance-wise is almost identical:
var myTask = Task.Run(async () =>
{
while (true)
{
var delayTask = Task.Delay(1000);
CPU_Load();
await delayTask;
}
});
I have omitted the ConfigureAwait(false)
because it's not really needed in this case. The ThreadPool
does not have a synchronization context that can be captured by the await
.
You could also consider using a Timer
to run periodically your work, but in my opinion the Task
-based approach is superior. It's quite tricky to enforce a non-overlapping execution policy with constant interval using a Timer
. Caveats:
- The
System.Timers.Timer
class is not thread-safe.
- It allows overlapping invocations of the event handler.
- It swallows any exceptions thrown inside the handler.
- It is possible for the
Elapsed
event to be raised after stopping the Timer
with the Stop
method.
- There is no easy way to stop the timer, and then wait for all running event handlers to complete.
- The class is disposable and needs to be disposed.