I have a series of long-running functions. I want to wrap them in a Task
so that I can run all of them concurrently, rather than waiting for each one to finish sequentially.
The method calls, and all relevant field values and methods and properties exist within a static class.
I'm having a problem wherein the static class constructor fails to complete because it is hanging when I wrap a method within with Task.Run
.
In compliance with the requisite Mininmal, Complete and Verifiable example requirements...
using System;
using System.Linq;
using System.Threading.Tasks;
namespace MCVEAsyncHang
{
class Program
{
private static readonly string[] _foo;
static Program()
{
_foo = Task.WhenAll(Task.Run(new Func<string>(One))).Result;
}
private static string One()
{
return "Foo";
}
private static void Print()
{
Console.WriteLine(
_foo.Aggregate((total, current) =>
total + string.Format("{0}{1}", Environment.NewLine, current)));
}
static void Main(string[] args)
{
Print();
Console.WriteLine("Done");
Console.ReadLine();
}
}
}
I understand I can just create some other method and call that ( and I will if I have to ( begrudgingly so ) ) but if it IS possible, I'd rather keep this within the static class constructor.
Your task, which will be running in another thread, needs to call _one
. That method can't execute until your Program
type has been initialized.
The tasks's thread will see that the Program
type is already being initialized in the main thread, and so will block until that thread has completed initializing the type. Unfortunately, that's not going to happen - because the type initializer is going to block until your task has finished. Deadlock.
Basically, you should avoid doing too much work in a static constructor. Launching tasks definitely feels like too much work. In this case the deadlock is obvious, but in other cases it could be much more subtle. (Before now I've spent hours debugging type initializer loops, and it's really, really not fun. That was single=threaded code - I dread to think how painful it would be in a multi-threaded environment.)
See more on this question at Stackoverflow