It usually depends on nature of your async work. If you do something like:
async () => {
// some heavy CPU work here
// then some IO
}
It's better to use Task.Run, because otherwise "heavy CPU work" will run on your current thread and you will gain little parallelization.
However, such situation is relatively rare, because for parallelization of heavy CPU work there are other tools. If you have something like this:
async () => {
// some async IO, like database call or web request
// some processing
// some more async IO
}
Then you don't need to Task.Run. Then you can use your second method:
Func<Task> t = async () => {
// some stuff
};
tasks.Add(t());
If you are doing that on UI thread (in WPF\WinForms) - ensure to use ConfigureAwait(false) inside your async delegate to prevent returning control to UI thread.
things?//do stuffcontains theawaitkeyword. StartNew does not handle anonymous functions declaredasyncTaskScheduler? when you don't specify one it usesTaskScheduler.FromCurrentSynchronizationContextwhich can make your task fromStartNewrun on the UI thread instead of a background thread if you are doing this from inside a task already on the background. The article I linked to describes this issue.