I'm creating a thread
Thread MyThread = new Thread(async () => await MyTask());
MyThread.Start();
It kinda doesn't make sense and that's the question of how to create it properly.
MyTask is an unending task which periodically starts cpu intensive work
async Task MyTask ()
{
while (true)
{
await Task.Run(() => CPU_Load());
await Task.Delay(1000).ConfigureAwait(false);
}
}
CPU_Load is a method where work is being done
void CPU_Load ()
{
*CPU_Load*
}
CodePudding user response:
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.Timerclass 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
Elapsedevent to be raised after stopping theTimerwith theStopmethod. - 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.
CodePudding user response:
Quoting a comment by Flydog57:
How about the original async strategy back when
Maincouldn't be async. Start your thread with a non-async function (or delegate or lambda). In that function that simply saysWhatIWantToDoAsync().Wait();that is async and returns a Task. Your thread function never returns, so waiting for it isn't going to do much.
