Author Topic: BackgroundWorker & ShowModalDialog  (Read 17380 times)

0 Members and 1 Guest are viewing this topic.

Bobby C. Jones

  • Swamp Rat
  • Posts: 516
  • Cry havoc and let loose the dogs of war.
BackgroundWorker & ShowModalDialog
« on: March 01, 2009, 07:33:31 PM »
From a UserControl on a palette, I start a background worker that when complete opens a drawing.  All is well until I launch a modal dialog from the palette.  After closing the modal dialog the next call to the background worker causes a fatal error and kills acad.  Any thoughts?  Thanks.

Code: [Select]
  public partial class UserControl1 : UserControl
  {
    public UserControl1()
    {
      InitializeComponent();
    }

    private void ShowModalFormButton_Click(object sender, EventArgs e)
    {
      Form1 modalForm = new Form1();

      acadApp.ShowModalDialog(modalForm);
    }

    private void OpenDrawingButton_Click(object sender, EventArgs e)
    {
      BackgroundWorker worker = new BackgroundWorker();
      worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
      worker.DoWork += new DoWorkEventHandler(worker_DoWork);
      worker.RunWorkerAsync();
    }

    void worker_DoWork(object sender, DoWorkEventArgs e)
    {
      //Long running process
    }

    void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
      //Long running process is complete.
      acadApp.DocumentManager.Open(@"C:\OftenUsedBlock.dwg", false);
    }
  }
Bobby C. Jones

Chuck Gabriel

  • Guest
Re: BackgroundWorker & ShowModalDialog
« Reply #1 on: March 02, 2009, 08:28:04 AM »
I wish I had some useful advice for you Bobby, but about the most intelligent-sounding thing I can come up with is maybe you have a deadlock.  Wouldn't that just hang the application though?

Draftek

  • Guest
Re: BackgroundWorker & ShowModalDialog
« Reply #2 on: March 02, 2009, 09:04:45 AM »
I don't believe the AutoCAD application supports multi-threading, does it?

I could be wrong but I usually save any threading to non-autocad related activities like showing a progress bar duing a long process, etc.

I could be wrong - don't tell my wife, though.

Bobby C. Jones

  • Swamp Rat
  • Posts: 516
  • Cry havoc and let loose the dogs of war.
Re: BackgroundWorker & ShowModalDialog
« Reply #3 on: March 02, 2009, 09:47:14 AM »
I don't believe the AutoCAD application supports multi-threading, does it?

I could be wrong but I usually save any threading to non-autocad related activities like showing a progress bar duing a long process, etc.

I could be wrong - don't tell my wife, though.

You are correct, you cannot interact with autocad on multiple threads.  And I didn't think that I was.  However, your post got me to thinking.  I modified the RunWorkerCompleted callback like so:

Code: [Select]
    void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
      //Long running process is complete.
      acadApp.ShowAlertDialog(this.InvokeRequired.ToString());
    }

This returns False until after the modal dialog is shown.  I'm sure there's a fundamental aspect of threading that I just don't grasp and this really does makes sense.  Maybe someone can help me to understand; I'm all ears.  In the meantime I'm going to test for InvokeRequired and invoke the call on the main thread as needed.
Bobby C. Jones

tjr

  • Guest
Re: BackgroundWorker & ShowModalDialog
« Reply #4 on: March 02, 2009, 10:41:26 AM »
I used BackgroundWorker quite a bit in a BOM app I created and I never had any luck running it from anything other than inside a windows form. From there I would do something like:

Code: [Select]
Form1 modalForm = new Form1();
if (modelForm.ShowDialog() == DialogResult.Ok)
{
   acadApp.DocumentManager.Open(modelForm.MyPublicStringThatContainsADrawingName, false);
}

When ShowDialog was called it would do all the BackgroundWorker stuff and I would then pass the results back in some form of public property.

Not sure if this answers your question or not, but this is the experience I had.

Draftek

  • Guest
Re: BackgroundWorker & ShowModalDialog
« Reply #5 on: March 02, 2009, 11:10:57 AM »
Here is what I've done - use a while (backgroundworker.IsBusy) loop and then open the drawing outside of the thread, instead of in the workcompleted event.

ReneRam

  • Guest
Re: BackgroundWorker & ShowModalDialog
« Reply #6 on: March 02, 2009, 11:23:59 AM »
 :|
Sorry, it's not relevant to this post, but I've been going through an issue like this, ModalFormDialog and opening a drawing a drawing while the form is open. I asked help to the ADN and it partially helped, I'm still working on the thing, but as long as I have understood until now it all involves the current editor when the dialog is shown.
I have moved part of my code from the form to the Commands module and launch it with a SendStringToExecute("OpenDrawing ", True, False, False) and the CommandMethod for the OpenDrawing with no CommandFlags.
As I said I'm still working on it, but the flags ".InProgress", "Transparent" and "Session" give different results, also AutoCAD crashing. I'm still testing and I'm looking for a good explanation of the exact meaning of the flags.

Bobby C. Jones

  • Swamp Rat
  • Posts: 516
  • Cry havoc and let loose the dogs of war.
Re: BackgroundWorker & ShowModalDialog
« Reply #7 on: March 02, 2009, 11:44:43 AM »
Hey Dt,
Doesn't that defeat the purpose of using a BackgroundWorker?  I need to capture progress and provide the ability to cancel the worker.

Here is what I've done - use a while (backgroundworker.IsBusy) loop and then open the drawing outside of the thread, instead of in the workcompleted event.
Bobby C. Jones

Bobby C. Jones

  • Swamp Rat
  • Posts: 516
  • Cry havoc and let loose the dogs of war.
Re: BackgroundWorker & ShowModalDialog
« Reply #8 on: March 02, 2009, 11:47:41 AM »
I've never tried to open a drawing from a modal form, which I would think goes against the purpose of a modal form anyway.  Sorry I couldn't be of more help.

:|
Sorry, it's not relevant to this post, but I've been going through an issue like this, ModalFormDialog and opening a drawing a drawing while the form is open. I asked help to the ADN and it partially helped, I'm still working on the thing, but as long as I have understood until now it all involves the current editor when the dialog is shown.
I have moved part of my code from the form to the Commands module and launch it with a SendStringToExecute("OpenDrawing ", True, False, False) and the CommandMethod for the OpenDrawing with no CommandFlags.
As I said I'm still working on it, but the flags ".InProgress", "Transparent" and "Session" give different results, also AutoCAD crashing. I'm still testing and I'm looking for a good explanation of the exact meaning of the flags.

Bobby C. Jones

Draftek

  • Guest
Re: BackgroundWorker & ShowModalDialog
« Reply #9 on: March 02, 2009, 12:28:25 PM »
Here is how I see it:

Your modal dialog is running inside the current application thread. as in - acadApp.ShowModalDialog()
You CANNOT do anything AutoCAD application specific (Like opening a drawing) inside another thread (your background worker).

Bobby C. Jones

  • Swamp Rat
  • Posts: 516
  • Cry havoc and let loose the dogs of war.
Re: BackgroundWorker & ShowModalDialog
« Reply #10 on: March 02, 2009, 02:01:21 PM »
I think that due to my poor explanation there's some confusion.  I'm not interacting with AutoCAD from the Modal Dialog; I'm only collecting info from the user.  In the example that I put together for this post, the modal form doesn't even have any controls on it.

I can press the Open Drawing button all day long and it will open the file.  But, if I press the button to display the modal dialog and then close that dialog, the next time I press the button to open the drawing, BOOM!

After my last findings I know what's going on, but I don't know why.  This project is sittin' until I git my edumication finsihed on these thread things.

Here is how I see it:

Your modal dialog is running inside the current application thread. as in - acadApp.ShowModalDialog()
You CANNOT do anything AutoCAD application specific (Like opening a drawing) inside another thread (your background worker).

Bobby C. Jones

Draftek

  • Guest
Re: BackgroundWorker & ShowModalDialog
« Reply #11 on: March 02, 2009, 03:51:14 PM »
I see, but it's still the same problem, just in reverse.

This is your problem:
Code: [Select]
   void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
      //Long running process is complete.
      acadApp.DocumentManager.Open(@"C:\OftenUsedBlock.dwg", false);
    }

Instead of opening the drawing here, have the background worker report back to the client (openDrawingButton_Click event) whether it was successful or not using a while loop to make sure the background worker is not busy as in:
while (myBackgroundworker.IsBusy)
{
application.DoEvents
}

Then if successful, open the drawing.

I re-created you code as above and clicked both buttons several times with no crashes..


 

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8690
  • AKA Daniel
Re: BackgroundWorker & ShowModalDialog
« Reply #12 on: March 02, 2009, 04:04:09 PM »
...  In the example that I put together for this post...


Can you post your sample solution so others might play? 

ReneRam

  • Guest
Re: BackgroundWorker & ShowModalDialog
« Reply #13 on: March 03, 2009, 04:58:01 AM »
Sorry Bobby, maybe I didn't explain myself well, I'm not suggesting a solution, I don't think I have the knowledge since I'm still trying to solve a similar issue, what I was trying to say is that maybe moving part of your code (the myBackgroundworker) to the Commands module and activating it with a CommandFlags like ".Transparent" could solve.
As much as I know I think, but I'm not sure, you can have only 1 Active Editor for each Session of AutoCAD, so when you you press the OpenDrawing, actually I think you are changing the Active Editor. The acadApp.ShowModalDialog() sort of "freezes" the current Editor until the dialog is open.
In my program I do something like this:

from the ModalDialog:
Code: [Select]
Public Sub MakeNewDWG()

 

        myForm.Hide()

        Application.DocumentManager.MdiActiveDocument.SendStringToExecute("MakeDoc ", True, False, True)

 

    End Sub


and from the Commands module:

Code: [Select]
    <CommandMethod("MakeDoc", CommandFlags.Session)> _

    Public Sub MakeDoc()

        Dim myDoc As ApplicationServices.Document

        myDoc = Application.DocumentManager.Add("c:\temp\myTemplate.dwt")

        myDoc.Database.SaveAs("c:\temp\myDwg.dwg", DatabaseServices.DwgVersion.Current)

        myDoc.CloseAndDiscard()

        myDoc = Application.DocumentManager.Open("c:\temp\myDwg.dwg", False)

    End Sub



This does not give any crash, I discovered that my problem was a matter of synchronization. When I exit the Dialog, even if I see my new drawing in the background, the Editor switches to the Editor that was opened when I launched the Dialog the first time.
If I change the CommandFlag, what I'm trying to do is actually change the current drawing in to the new one, so like in your case change the active Editor, I get different kind of results, even having my new drawing filled with the ents created by my code, but with No Editor accessible to the User when I exit the Code in the Dialog.

So as I said in my previous post, I'm not trying to give a solution, but just suggesting to explore the idea of moving the Backgroundworker in a command that works "Transparent" to the current session and having it change a public variable that you can check before anything else, in this way I think you have much more control on what's happening

Bobby C. Jones

  • Swamp Rat
  • Posts: 516
  • Cry havoc and let loose the dogs of war.
Re: BackgroundWorker & ShowModalDialog
« Reply #14 on: March 03, 2009, 03:27:00 PM »
Hey Daniel, I'll post it tonight.

...  In the example that I put together for this post...


Can you post your sample solution so others might play? 
Bobby C. Jones