Background processes monitoring or checking

Background processes monitoring or checking

c_hanschen
Advocate Advocate
4,554 Views
18 Replies
Message 1 of 19

Background processes monitoring or checking

c_hanschen
Advocate
Advocate

Is there a way to 'ask' the Revit API what background processes are running? To monitor them?

 

I'm countering the following problem:

I have a lot of different tasks to complete.

all working just fine fired 1 at the time.

If I fire them up to quick after each other, Revit Crashes!

When I let my code take a break between tasks, the crashes are solved or strongly reduced.

I now use a timer to start the tasks with a pause of some seconds, working fine most of the time.

But when my PC is Bussy doing something else, and the resources for Revit are low, those seconds are not enough and Revit Crashes again.

 

I think this is because the new task is started while in the background the previous task is not completely finished, no I need to ask Revit for any running background processes, if any running, than the code will wait for it to end before starting  a new task.

 

Is there a way to 'ask' the Revit API what background processes are running? To monitor them?

 

Chris Hanschen

LKSVDD architecten 

Enschede, The Netherlands.

 

0 Likes
Accepted solutions (1)
4,555 Views
18 Replies
Replies (18)
Message 2 of 19

matthew_taylor
Advisor
Advisor

Hi @c_hanschen,

This post may help https://stackoverflow.com/questions/12035210/how-to-determine-total-unused-physical-memory-in-vb-net

If you want to know how much memory Revit is using, you may have to use https://stackoverflow.com/questions/27684486/ram-memory-usage-for-windows-application, although there are RevitWorker.exe processes now, along with RevitAccelerator.exe, so you may need to use https://stackoverflow.com/questions/10348180/list-all-processes-that-currently-running-on-windows-by... to get all processes, and check their names for 'Revit' (or something), and add their values. Of course, you may have more than one Revit instance running, so you may need to check for the .Parent.Id value.


Cheers,

-Matt
_______________________________________________________________________________
Marking a post as a 'solution' helps the community. Giving a post 'Kudos' is as good as saying thanks. Why not do both?
Message 3 of 19

c_hanschen
Advocate
Advocate

Hello matthew taylor

 

Thanks for your reply.

not the answer I was hoping for, but I will give it a try.

I was hoping for a IsApplicationBusy function or a function to get (a list of) running background processes or something like that 🙂

 

thanks anyway.

 

Chris

 

0 Likes
Message 4 of 19

matthew_taylor
Advisor
Advisor
Hi Chris,
No problem.
You need to be more descriptive to get a non-general answer. 😉
Perhaps you should browse Revit events?
What 'processes' are you running?
Do you actually mean Windows processes, or something else?
What APIs are you using?
What version of Revit?
If 2018, have you seen my Known Bug List post? I personally think some of the exporting functions that have issues sound like thread/background process issues.
https://forums.autodesk.com/t5/revit-architecture-forum/known-bug-list/td-p/7079586
More data, please. 😉

Cheers,

-Matt
_______________________________________________________________________________
Marking a post as a 'solution' helps the community. Giving a post 'Kudos' is as good as saying thanks. Why not do both?
Message 5 of 19

BobbyC.Jones
Advocate
Advocate
Accepted solution

How are you launching your 'tasks', from code behind in a dialog box?

--
Bobby C. Jones
Message 6 of 19

c_hanschen
Advocate
Advocate

Yes, the tool is a Dialog box with a lot of choices, choose the tasks you want, each tasks has it own customize-able settings.

 

@matthew_taylor

Current using Revit 2017.2

Visual Studio 2015 professional, Language Vb.net

 

By Example:

When printing different sheets and immediately after that exporting sheets to DWG, Revit crashes.
When waiting between those 2 tasks, the problem is solved.

btw waiting with system.threathing.sleep doesn't work, a temporary visible dialog closing down by a timer does the job,

I somehow think this has something to do with running background processes. that's why I ask if there is any way to monitor the running background processes.

 

Chris 

0 Likes
Message 7 of 19

BobbyC.Jones
Advocate
Advocate

@c_hanschen wrote:

Yes, the tool is a Dialog box with a lot of choices, choose the tasks you want, each tasks has it own customize-able settings....

 

Chris 


Chris,

I assume that the dialog is modeless, if that's not the case then you can stop reading now as I'm way off track.  

 

There has been A LOT of discussion on this in the past.  Here's an excellent resource from Jeremy's blog to read up on some of it, http://thebuildingcoder.typepad.com/blog/about-the-author.html#5.28

 

In a nutshell, the Revit API can only be accessed from the main thread.  Accessing it from a different thread, like from code behind in a modeless window, will cause errors, insidious errors in that sometimes the code will appear to work, and other times it will not.

 

The generally accepted way to handle this is via the external events framework.  Here's a fairly succinct explanation and example of it, https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2016/ENU/Revit-API/files/GUID-...

 

Hope that helps!

--
Bobby C. Jones
Message 8 of 19

BobbyC.Jones
Advocate
Advocate

Chris,

I assume that the dialog is modeless, if that's not the case then you can stop reading now as I'm way off track.  

 

There has been A LOT of discussion on this in the past.  Here's an excellent resource from Jeremy's blog to read up on some of it, http://thebuildingcoder.typepad.com/blog/about-the-author.html#5.28

 

In a nutshell, the Revit API can only be accessed from the main thread.  Accessing it from a different thread, like from code behind in a modeless window, will cause errors, insidious errors in that sometimes the code will appear to work, and other times it will not.

 

The generally accepted way to handle this is via the external events framework.  Here's a fairly succinct explanation and example of it, https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2016/ENU/Revit-API/files/GUID-...

 

Hope that helps!

--
Bobby C. Jones
0 Likes
Message 9 of 19

c_hanschen
Advocate
Advocate

@BobbyC.Jones,

 

The Windows Form is called by 'ShowDialog', so it is modal and return to it's code after closing the Form. (Dialog)

 

The code is like this:

 


<Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)>
<Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)>
Public Class DeleteViewsNotOnSheets
Implements IExternalCommand
Private Function IExternalCommand_Execute(commandData As ExternalCommandData, ByRef message As String, elements As ElementSet) As Result Implements IExternalCommand.Execute

Dim MyDialog As New DialogDeleteViewsNotOnSheet(commandData)
MyDialog.ShowDialog()

Return Result.Succeeded

End Function
End Class

 

The Api call is closed with 'return succeeded' after closing the dialog.

within the dialog there a multiple transactions, some off them are rolled-back for testing purpose only, other transactions are committed.

 

Am I doing something wrong by calling a Dialog like this? (Revit Wise)

 

This code allways returns succeeded, other tool are returning cancelled depending on the outcome of the dialog.

Do not really see the point in this, when the tool is cancelled, the transaction (or transactiongroup) is rolled-back and I can still return succeeded when leaving the API call.

 

Chris 

0 Likes
Message 10 of 19

swfaust
Advocate
Advocate

I think someone asked before but how are you spinning off background processes?  If you are just starting threads or background workers in your code you could just track the number of background workers running as you call them.  In simplest form, create an integer variable in the dialog scope, when you start a background worker add 1 to it, also add a 'RunWorkerCompleted' handler and -1 to the variable in it so it removes itself from the count when the task is complete.  If the variable is 0 there aren't any running.

 

That being said, why are you running these as background processes?  I have found that Revit API generally doesn't 'like' to be run from another thread and always seems to be a little less stable when I have tried.  Plus if you are trying to run them all in sequence anyway then there really isn't an advantage to running them in the background, why not just run them in a straighforward sequential execution?  If you want to start several tasks and have them run sequentially just make your dialog have checkboxes or something for all the items you want to do and then you check off what you want to run and start the whole thing and it runs them all on after another.

0 Likes
Message 11 of 19

BobbyC.Jones
Advocate
Advocate

@c_hanschen wrote:

 

The Windows Form is called by 'ShowDialog', so it is modal and return to it's code after closing the Form. (Dialog)

 


Because this is a modal dialog, and without seeing actual code, I can't say for certain that your crashing is due to threading issues.  I.O.W., I may be leading you down the wrong path.

 


@c_hanschen wrote:

 

Am I doing something wrong by calling a Dialog like this? (Revit Wise)


The short answer is no.  I don't like code behind, but for simple modal dialogs it can work.  So ,even though I don't know for sure this is a threading issue, I still suspect it, and if this were my code the first thing I would do to troubleshoot is yank all Revit API calls out of the code behind.  Of course that's easy for me to say, it's not my code  🙂

--
Bobby C. Jones
Message 12 of 19

c_hanschen
Advocate
Advocate

@swfaust

"That being said, why are you running these as background processes?"

I am NOT! I use background workers in standalone Windows Applications, but never in Addins, not in Revit, not in Word or what so ever.

What I meant is, that I think that after calling a Revit Call, the call is partly processed by Revit in a background process. (finishing up)

And when you start a more than one Revit Api Call (not simultaneously, but after each other) the still running background processen are messed up.

 

Thanks anyway for your response

 

Chris

 

0 Likes
Message 13 of 19

c_hanschen
Advocate
Advocate

@BobbyC.Jones,

 

"and if this were my code the first thing I would do to troubleshoot is yank all Revit API calls out of the code behind."

 

Where to put the code? it's now party in the code of the Form and partly in Modules. (VB.net)

Are Modules save to use? I use a lot of Modules so I can share them (linked files) over more than 1 Addin.

Is what you are saying, all the code should be in the same file as the 'IExternalCommand.Execute'...??

 

Chris

0 Likes
Message 14 of 19

BobbyC.Jones
Advocate
Advocate

@c_hanschen wrote:

@BobbyC.Jones,

 

"and if this were my code the first thing I would do to troubleshoot is yank all Revit API calls out of the code behind."

 

Where to put the code? it's now party in the code of the Form and partly in Modules. (VB.net)

Are Modules save to use? I use a lot of Modules so I can share them (linked files) over more than 1 Addin.

Is what you are saying, all the code should be in the same file as the 'IExternalCommand.Execute'...??

 

Chris


No, break it out into classes and modules as you see fit.  The main thing is to separate UI code from the code that does the work.  A basic pattern I use with a dialog is to treat the IExternalCommand.Execute() method as a controller.  It simply spins up the dialog, determines if the user cancelled or proceeded, and runs tasks using the collected data.  I prefer the MVVM pattern:

 

    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]
    public class InsertNoteCommand : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            var notesVM = new NotesViewModel(commandData.Application);

            var notesWindow = new SearchableAnnotationsView {DataContext = notesVM};

            var dialogResult = notesWindow.ShowDialog();

            if (dialogResult != true)
                return Result.Cancelled;

            var note = CommonNote.Create(notesVM.SelectedNote);

            var insertSuccess = note.Insert(notesVM.TextRotation, commandData.Application.ActiveUIDocument);

            return insertSuccess ? Result.Succeeded : Result.Failed;
        }
    }

This allows you to test your task completely independent of the UI.  Or reuse it with a different, or no, UI.  And I believe this separation would help you isolate and diagnose these errors much better.

 

    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]
    public class TestNoteCommand : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            var text = "This is a test note.";

            var note = CommonNote.Create(text);

            var insertSuccess = note.Insert(TextRotation.Horizontal, commandData.Application.ActiveUIDocument);

            return insertSuccess ? Result.Succeeded : Result.Failed;
        }
    }

 

 

 

 

--
Bobby C. Jones
Message 15 of 19

c_hanschen
Advocate
Advocate

@BobbyC.Jones

 

Thanks for all your replies..!!

 

I'm displaying a large progressbar om my dialog to show the complete progress of my tasks, this will be difficult than.

But I will give it a try, to shut down the dialog after collecting all the user input data and handle it in IExternalCommand.Execute()

This will be later this week, but I will update you on the outcome.

 

Thanks!

 

Chris Hanschen

LKSVDD architecten Enschede

The Netherlands

0 Likes
Message 16 of 19

matthew_taylor
Advisor
Advisor

@c_hanschen,

I have to agree with @BobbyC.Jones about code separation. It makes things a lot simpler.

You can always pop up a progress dialog, but get it working first!

 

I usually get the code working, then add the UI. The code runs the dialog, not the dialog running the code.

 

Let us know how you get on.


Cheers,

-Matt
_______________________________________________________________________________
Marking a post as a 'solution' helps the community. Giving a post 'Kudos' is as good as saying thanks. Why not do both?
Message 17 of 19

swfaust
Advocate
Advocate

Gotcha, sorry I misunderstood then.  I would agree with the others then, try testing the code independently of the dialog and then start adding UI layer on to it and see if you start getting an issue...

0 Likes
Message 18 of 19

c_hanschen
Advocate
Advocate

comment of @BobbyC.Jones: "How are you launching your 'tasks', from code behind in a dialog box?"

 

I accepted this comment as solution..!!!

 

I removed the code from behind my Dialog to the 'IExternalCommand.Execute' Class/Function and the problem was solved..!!

 

Thank you guys a lot, I never thought that this could be the problem.

 

It sets me way back in functionality of my tool, because now the progress indicator is gone and the cancel-function is gone too.

I have to rewrite that functionality, but that may not be the problem...

 

THANKS, THANKS, THANKS..!!

 

Chris Hanschen

LKSVDD architecten Enschede

The Netherlands

Message 19 of 19

c_hanschen
Advocate
Advocate

@BobbyC.Jones and @swfaust,

 

this story continues on page:

https://forums.autodesk.com/t5/revit-architecture-forum/known-bug-list/m-p/7145065/highlight/false#M...

 

Chris Hanschen

LKSVDD Architecten Enschede

The Netherlands

0 Likes