title: Singleton Async Loading List Property
body: <p>I have a winforms application with a singleton class that contains a property (list) that is the datasource for a search grid.  Filling this property takes a significant amount of time (>1 minute) so, I want to start filling this property asynchronously when the user launches the program.  </p>
  
  <p>The main form has a button to launch another search form.  If, when the user launches the search if the datasource is ready then, no problem.  However, if the datasource is still filling, the user sees a wait cursor and the search grid <em>should</em> fill as soon as the datasource has finished populating.</p>
  
  <p>To do this, I created a method that fires after the asynchronous method completes and then the grid is bound to the datasource.</p>
  
  <p>Everything appears to work correctly, the event fires, and then I try to bind the list to the grid and nothing happens... Debugging halts and I never hit the next line of code (see comments in FrmSearch.cs).</p>
  
  <p>Any ideas relating to what is going wrong or general code improvements would be very much appeciated, thanks!</p>
  
  <p>Program.cs</p>
  
  <pre><code>static class Program
      {
          [STAThread]
          static void Main()
          {
              Application.EnableVisualStyles();
              Application.SetCompatibleTextRenderingDefault(false);
  
              Task.Run(async() =&gt; { Singleton.DogsList = await Dogs.FindAllAsync(); });
  
              Application.Run(new FrmMain());
          }
      }
  </code></pre>
  
  <p>Singleton.cs</p>
  
  <pre><code>public static class Singleton
      {
          public static event DogsListHandler DogsListLoaded;
          public delegate void DogsListHandler(object sender, EventArgs e);
  
          public static BindingList&lt;Dogs&gt; DogsList
          {
              get
              {
                  if (dogsList == null)
                  {
                      Task.Run(async () =&gt; 
                      {
                          dogsList = await Dogs.FindAllAsync();
                          notifyListLoaded();
                      });
                  }
                  return dogsList;
              }
              set { dogsList = value; }
          }
          private static BindingList&lt;Dogs&gt; dogsList;
          private static void notifyListLoaded()
          {
              if (DogsListLoaded != null) { DogsListLoaded(null, EventArgs.Empty); }
          }
      }
  </code></pre>
  
  <p>FrmSearch.cs</p>
  
  <pre><code>public partial class FrmSearch : Form //launched using the .Show() method from a button on the main form
  {
      public FrmSearch()
      {
          InitializeComponent();
      }
  
      private void FrmSearch_Load(object sender, EventArgs e)
      {
          Singleton.DogsListLoaded += new Singleton.DogsListHandler(Dogs_ListLoaded);
  
          Cursor = Cursors.WaitCursor;
          if (Singleton.DogsList != null)
          {
              grid.DataSource = Singleton.DogsList;
              Cursor = Cursors.Default;
          }
          else { Cursor = Cursors.WaitCursor; }
      }
  
      public void Dogs_ListLoaded(object sender, EventArgs e)
      {
          grid.DataSource = Singleton.DogsList; //freezes here
          Cursor = Cursors.Default; //this line never gets hit
      }
  }
  </code></pre>
  
  <p>Dogs.cs (will pull from db normally but just doing some iteration for the sample)</p>
  
  <pre><code>public class Dogs
      {
          public string Name { get; set; }
          public string Breed { get; set; }
          public int Age { get; set; }
          public string Summary { get { return string.Format("Name: {0} / Breed: {1} / Age: {2}", Name, Breed, Age.ToString()); } }
  
          public static async Task&lt;BindingList&lt;Dogs&gt;&gt; FindAllAsync()
          {
              BindingList&lt;Dogs&gt; dl = new BindingList&lt;Dogs&gt;();
  
              await Task.Run(() =&gt;
              {
                  int i = 0;
                  while (i &lt;= 999999)
                  {
                      dl.Add(new Dogs() { Name = "River" + i.ToString(), Breed = "Border Collie", Age = 3 });
                      dl.Add(new Dogs() { Name = "Jack" + i.ToString(), Breed = "Labrador", Age = 2 });
                      dl.Add(new Dogs() { Name = "Emma" + i.ToString(), Breed = "Beagle", Age = 7 });
                  i++;
                  }               
              });
              return dl;
          } 
      }
  </code></pre>