title: Task (or thread) requires Wait or Join to work
body: <p>I am trying to make a plugin type system.  I have made something along these lines in the past where all plugins execute in the main thread, which leads to problems if the plugins are taking a long time.  So I thought I'd execute the appropriate methods in each plugin using Tasks.  </p>
  
  <p>I have a main program, which loads each plugin using Assembly.LoadFile, and then reacts to commands a user types.  If one of these commands is handled by a plugin (the plugins report what commands they handle, the main program asks when it loads them), my program will start a method in the plugin in its own Task.</p>
  
  <pre><code>Task t = Task.Factory.StartNew(() =&gt; Plugin.ProcessCommand(cmd, Params, Context));
  </code></pre>
  
  <p>Each plugin also implements an event used when it has data to send to the main program for output.  The main program attaches a handler to this event when it loads each plugin.</p>
  
  <p>The plugin's ProcessCommand method does whatever work is needed, triggers the OnOutput event, and then ends.  </p>
  
  <p>This is a very simple plugin:</p>
  
  <pre><code>public override void ProcessCommand(PluginCommand Command, PluginParameters Parameters, PluginContext Context)
  {
      OnOutputGenerated(this,"Hello from Plugin A");
  }
  </code></pre>
  
  <p>This worked fine with the first plugin I made.  So I created another, using the exact same code, just changing "Hello from Plugin A" to "Hello from Plugin B."</p>
  
  <p>Plugin A always works.  If I issue the appropriate command in the main program, it runs and says Hello from Plugin A.  Great.</p>
  
  <p>The problem is: Plugin B executes maybe one in every 30 attempts.  I've discovered, however, that if call the plugin in the following way, it works every time:</p>
  
  <pre><code>Task t = Task.Factory.StartNew(() =&gt; Plugin.ProcessCommand(cmd, Params, Context));
  t.Wait(100);
  </code></pre>
  
  <p>Is there a technical reason why this might help?  I've read through pretty much all of <a href="http://www.albahari.com/threading/" rel="nofollow">http://www.albahari.com/threading/</a> trying to figure things out, but I've not had any luck.</p>
  
  <p>It's worth noting that I've also done this with threads, with the same problem. </p>
  
  <pre><code>Thread t = new Thread(() =&gt; Plugin.ProcessCommand(cmd, Params, Context));
  t.Start();
  </code></pre>
  
  <p>Adding:</p>
  
  <pre><code>t.Join(100);
  </code></pre>
  
  <p>"fixed" it.</p>
  
  <p><strong>Updated</strong></p>
  
  <p>I've simplified everything.  I've made a new project, which strips out all the code unrelated to the bugs.</p>
  
  <pre><code>foreach (string File in Directory.GetFiles(PluginDir, "*.dll")) {
  
      try {
  
          IPlugin Plugin = PluginManager.LoadPlugin(File);
          Plugin.OnOutputGenerated += new PluginOutputEvent(Plugin_OnOutputGenerated);
  
      } catch (Exception ex) {
  
      }
  
  }
  
  // main loop
  
  string Line = Console.ReadLine();
  
  foreach (IPlugin Plugin in PluginManager.LoadedPlugins) {
  
      foreach (PluginCommand cmd in Plugin.GetCommands()) {
  
          if (cmd.Command.Equals(Line, StringComparison.InvariantCultureIgnoreCase)) {
  
              PluginParameters Params = cmd.TryParseParameters(ParamString);
              Task t = Task.Factory.StartNew(() =&gt; Plugin.ProcessCommand(cmd, Params, Context));
  
          }
  
      }
  
  }
  
  // output handler
  
  static void Plugin_OnOutputGenerated(IPlugin Plugin, string OutputString) {
  
      Console.WriteLine("Output: " + OutputString);
  
  }
  </code></pre>
  
  <p>The main issue has changed.  Previously, one of the plugins didn't work most of the time.  Imagine two plugins.  </p>
  
  <p><em>Plugin A</em><br>
  * Has one command: CommandA<br>
  * Command triggers OnOutputGenerated event with the string "Hello from Plugin A"</p>
  
  <p><em>Plugin B</em><br>
  * Has one command: CommandB<br>
  * Command triggers OnOutputGenerated event with the string "Hello from Plugin B"</p>
  
  <p>If I run this new project I've made, and issue the command "CommandA", it will return "Hello from Plugin B".  It continues doing this until I actually issue "CommandB".  Once I've done that, it prints "Hello from Plugin B" (as it should).  If I then issue "CommandA" again, it returns "Hello from Plugin A" (as it should have originally).</p>
  
  <p>If I add </p>
  
  <pre><code>t.Wait(100);
  </code></pre>
  
  <p>it's fixed.  It still seems to be related to the Task somehow, but I'm at a loss to explain how.  It would appear that my logic otherwise is fine.  I can't see how it would execute Plugin B when it should execute Plugin A, or vice-versa.</p>