Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. OpenFileDialog works from app but not from a spawned thread after use InvokeMember to load assembly / class

OpenFileDialog works from app but not from a spawned thread after use InvokeMember to load assembly / class

Scheduled Pinned Locked Moved C#
csharpmobilevisual-studiodesigndebugging
4 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    JudyL_MD
    wrote on last edited by
    #1

    I've stripped my problem down to the bare minimum. I've got a form that, in response to user action, needs to display the OpenFileDialog dialog. When this form is started "normally" i.e. using Application.Run, the dialog appears. When this form is started via reflection it fails. Fails in this case means that the code successfully runs all the way to the actual OpenFileDialog.ShowDialog call -- ShowDialog is stepped into but the dialog never appears and the call never returns. Here's the code: The direct app:

    using UiLibrary;
    namespace DirectApp
    {
    static class Program
    {
    [STAThread]
    static void Main ()
    {
    Application.EnableVisualStyles ();
    Application.SetCompatibleTextRenderingDefault (false);
    Application.Run (new Form1 ());
    } } }

    The indirect app:

    namespace IndirectApp
    {
    public partial class DummyFormToLaunchTheRealUI
    {
    public DummyFormToLaunchTheRealUI () { InitializeComponent (); }

    private void button1\_Click (object sender, EventArgs e)
    {
      Assembly abs = Assembly.LoadFile (@"C:\\temp\\tester\\UiLibrary\\bin\\debug\\UiLibrary.dll");
      Type startType = abs.GetType ("UiLibrary.Startup", true);
      object startLib = startType.InvokeMember ("", BindingFlags.CreateInstance, null, null, new object\[0\]);
      startType.InvokeMember ("Run", BindingFlags.InvokeMethod, null, startLib, new object\[0\]);
    

    } } }

    The library:

    namespace UiLibrary
    {
    public class Startup
    {
    public void Run ()
    {
    Thread runThread = new Thread (new ThreadStart (ActualWork));
    runThread.Start ();
    }

    private void ActualWork ()
    {
      Form1 f = new Form1 ();
      f.ShowDialog ();
    }
    

    }

    public partial class Form1 : Form
    {
    public Form1 () { InitializeComponent (); }

    private void button1\_click (object sender, EventArgs e)
    {
      OpenFileDialog ofd = new OpenFileDialog ();
      // this field always correct
      ofd.InitialDirectory = Environment.ExpandEnvironmentVariables (@"%USERPROFILE%\\Downloads");
      // doesn't change if call ShowDialog with no paramters
      ofd.ShowDialog (this);
    

    } } }

    I've got to show Form1 from the library in its own thread since I want IndirectApp to remain responsive to UI. This is stripped down - in my real code Form1 is much more complex, successfully launching its own forms and doing other stuff regardless of which method is use to fire it up. Visual Studio 2012 using .NET 3.5 on

    Richard DeemingR 1 Reply Last reply
    0
    • J JudyL_MD

      I've stripped my problem down to the bare minimum. I've got a form that, in response to user action, needs to display the OpenFileDialog dialog. When this form is started "normally" i.e. using Application.Run, the dialog appears. When this form is started via reflection it fails. Fails in this case means that the code successfully runs all the way to the actual OpenFileDialog.ShowDialog call -- ShowDialog is stepped into but the dialog never appears and the call never returns. Here's the code: The direct app:

      using UiLibrary;
      namespace DirectApp
      {
      static class Program
      {
      [STAThread]
      static void Main ()
      {
      Application.EnableVisualStyles ();
      Application.SetCompatibleTextRenderingDefault (false);
      Application.Run (new Form1 ());
      } } }

      The indirect app:

      namespace IndirectApp
      {
      public partial class DummyFormToLaunchTheRealUI
      {
      public DummyFormToLaunchTheRealUI () { InitializeComponent (); }

      private void button1\_Click (object sender, EventArgs e)
      {
        Assembly abs = Assembly.LoadFile (@"C:\\temp\\tester\\UiLibrary\\bin\\debug\\UiLibrary.dll");
        Type startType = abs.GetType ("UiLibrary.Startup", true);
        object startLib = startType.InvokeMember ("", BindingFlags.CreateInstance, null, null, new object\[0\]);
        startType.InvokeMember ("Run", BindingFlags.InvokeMethod, null, startLib, new object\[0\]);
      

      } } }

      The library:

      namespace UiLibrary
      {
      public class Startup
      {
      public void Run ()
      {
      Thread runThread = new Thread (new ThreadStart (ActualWork));
      runThread.Start ();
      }

      private void ActualWork ()
      {
        Form1 f = new Form1 ();
        f.ShowDialog ();
      }
      

      }

      public partial class Form1 : Form
      {
      public Form1 () { InitializeComponent (); }

      private void button1\_click (object sender, EventArgs e)
      {
        OpenFileDialog ofd = new OpenFileDialog ();
        // this field always correct
        ofd.InitialDirectory = Environment.ExpandEnvironmentVariables (@"%USERPROFILE%\\Downloads");
        // doesn't change if call ShowDialog with no paramters
        ofd.ShowDialog (this);
      

      } } }

      I've got to show Form1 from the library in its own thread since I want IndirectApp to remain responsive to UI. This is stripped down - in my real code Form1 is much more complex, successfully launching its own forms and doing other stuff regardless of which method is use to fire it up. Visual Studio 2012 using .NET 3.5 on

      Richard DeemingR Offline
      Richard DeemingR Offline
      Richard Deeming
      wrote on last edited by
      #2

      I suspect your background thread needs to be an STA thread. Try changing your Startup.Run method:

      public void Run()
      {
      Thread runThread = new Thread(ActualWork);
      runThread.ApartmentState = ApartmentState.STA;
      runThread.Start();
      }


      "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

      "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

      J RaviBeeR 2 Replies Last reply
      0
      • Richard DeemingR Richard Deeming

        I suspect your background thread needs to be an STA thread. Try changing your Startup.Run method:

        public void Run()
        {
        Thread runThread = new Thread(ActualWork);
        runThread.ApartmentState = ApartmentState.STA;
        runThread.Start();
        }


        "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

        J Offline
        J Offline
        JudyL_MD
        wrote on last edited by
        #3

        And the prize goes to Richard!!! That fixed the issue. Must be something that the common file dialogs need that your plain old ordinary user-created form doesn't. THANKS!!!:thumbsup: Judy

        Be wary of strong drink. It can make you shoot at tax collectors - and miss. Lazarus Long, "Time Enough For Love" by Robert A. Heinlein

        1 Reply Last reply
        0
        • Richard DeemingR Richard Deeming

          I suspect your background thread needs to be an STA thread. Try changing your Startup.Run method:

          public void Run()
          {
          Thread runThread = new Thread(ActualWork);
          runThread.ApartmentState = ApartmentState.STA;
          runThread.Start();
          }


          "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

          RaviBeeR Offline
          RaviBeeR Offline
          RaviBee
          wrote on last edited by
          #4

          Good catch. :thumbsup: /ravi

          My new year resolution: 2048 x 1536 Home | Articles | My .NET bits | Freeware ravib(at)ravib(dot)com

          1 Reply Last reply
          0
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • World
          • Users
          • Groups