Interface updates while busy


#1

I am using Windows 7 and max 2011, and I think perhaps this is a windows issue rather than max/maxscript, but the problem affects the running of scripts in a very damaging way, so I try to ask about it here.

Whenever I run a script that has a running time of more than a few seconds, the dialog/max interface inevitably freezes with a “Not responding” note in the window title bar, and UI changes like in progress bars or maxscript listener no longer update, until the script has finished. This is really annoying, as many of my scripts work with large datasets and take a long time to complete. Now I have no idea when they will finish, or how they are doing.

It seems to me like this is perhaps some automatic windows safeguard to prevent bugged applications from destroying windows UI performance?


#2

Yeah, it’s very annoying!

http://forums.cgsociety.org/showthread.php?f=98&t=905710

Davy


#3

Thanks for the link. I also found some info on the net. Disabling the following service seems to do the trick, although I’m uncertain about any side effects this might have:

Windows 7 64bit Ultimate: Control Panel -> System and Security -> Administrative Tools -> Services -> Desktop Window Manager Session Manager

It seems to interfere with general redraw so that although my progress bar will now draw correctly through the whole execution, the rest of my dialog interface does not recover from the overlapping OpenFile dialog (which has just been closed) until execution is done. However, this is probably the way it always used to be? When running scripts in XP I would often end up looking at a “dead” screen where only the progress bar was updating.


#4

Well, the only “almost” perfect way around it that I found (and know about) so far is using ProgressStart End and Update. That perfectly prevents windows from stalling the 3ds Maxs UI.

But the side effect is that it will hide all UI elements unless you fool with it like I do but it only works for custom local scripts (without users) as the viewport is fully exposed during run time.

Davy


#5

Yeah, disabling that service seems to disable everthing “Aero”, so I guess many would shy away from that. It saves me rewriting all my old scripts though.


#6

Not sure I fully understood the problem you are having…
when you run your script, since it takes a lot of time (for whatever reasons), 3dsmax “freezes” until it finishes running your script, right?

You could use dotnetobject “CSharpUtilities.SynchronizingBackgroundWorker”
in order to run whatever function you want asynchronously. This will prevent 3dsmax from freezing.


#7

Well, max does “freeze”, but that is ok, I don’t really want to be doing other stuff in max while my script is running. The problem is that Windows 7 decides that max/maxscript is hanging/not responding and therefore shuts down UI updates in max/maxscript windows, even if my script is making calls to (a local) progress bar or maxscript listener.

As discussed in the other thread mentioned above, rewriting a script to use the “global” max progress bar will circumvent the issue. It’s a case of either max being sloppy about letting windows know something is still happening or windows being too quick to decide nothing is happening, but I don’t know which.

Disabling the service mentioned above stops the erroneous behaviour (and Aero with it). There appears to be other workarounds too, including your suggestion.


#8

The annoying thing is that 3ds Max is not stalling or freezing, it “is” calculating things and doing stuff…but it is just the combination of the OS not knowing that 3ds Max is still busy, even if you update with a pushPrompt etc.

I also searched a registry to disable that from happening, or increase the time when windows decides a progam is not responding, no luck.

In general, I hate this kind of behaviour of windows. I can know myself when a program is not responding, I don’t need windows to decide that for me. If you could disable that, quite sure you can somehow…all would be fixed.

Davy


#9

Hopefully it is not just about “knowing” that an application is “not responding”, but also about taking precautions so that the application in question does not impact system stability (access to cpu/memory resources etc.). If that is the case, then the functionality at least makes some sense. However, it’s clearly not working as intended in this instance.


#10

Well, it is just for users convinience I suppose cause that thing that happens does not prevent 3ds Max from using more memory nor restricting CPU resources…it keeps ongoing no mather what.

So for me so far, that feature of windows does not do anything useful other than annoying me :slight_smile:

Davy


#11

It would be helpful if someone posted a bare bones repro of their script and how they trigger it. Are you triggering the long calculation from a (modal) dialog, the utility panel, in a timer event…

I have found the usual solution is to do my heavy lifting on a background worker thread. There are lots of different ways to set this up, that’s why I’m interested in how what the problem script looks like now.

For the ‘why it works this way’ you might want to check out:

Preventing Hangs in Windows Applications

As a last resort you can probably call DisableProcessWindowsGhosting but your users will curse you …and your peers will know you cheated :slight_smile:

This a user32 library call so you will have to expose it with a little bit of C#. DenisT has tons of examples of how to do this on the fly:

http://forums.cgsociety.org/showthread.php?f=98&t=850382&highlight=user32

.biddle


#12

For me it is not always the heavy calculations that stall 3ds Max. Even adding modifiers on a bunch of objects can cause it. Well, some modifiers itself cause this issue, like the ProOptimizer and things like that that require a little bit of time.

I don’t see any benefits of doing these common things with a background worker although I need to take a closer look to be sure.

Davy


#13

How about this one (in maxscript):

windows.processPostedMessages()

I gave it an occational call within my loop, seemed to work wonders for me…

btw, I didn’t find this in maxscript help, but if you type windows.giveMeAClue into the listener, you will get some :slight_smile:

Also, I ran this by doing timestamps every iteration and then windows.processPostedMessages() every 3 seconds. The overhead for a 64 second process was about 1 second.


#14

Great find.

I looked it up in the SDK --it’s in the mxsagni\windows.cpp sample code.


#15

what version of MAX are we talking about?


#16

It’s in the 2011 SDK, but not in the 2009 SDK (I don’t have 2010 installed)

I guess I don’t feel too bad about not noticing it earlier :slight_smile:

In 2011 you get:

windows.foo()
– Unknown property: “foo” in #Struct:windows(
getChildrenHWND:<fn>; Public,
getDesktopHWND:<fn>; Public,
getChildHWND:<fn>; Public,
postMessage:<fn>; Public,
getHWNDData:<fn>; Public,
sendMessage:<fn>; Public,
getMAXHWND:<fn>; Public,
addChild:<fn>; Public,
processPostedMessages:<fn>; Public)

but all 2009 has is:

windows.foo()
– Unknown property: “foo” in #Struct:windows(
getDesktopHWND:<fn>,
addChild:<fn>,
getChildrenHWND:<fn>,
getChildHWND:<fn>,
sendMessage:<fn>,
getMAXHWND:<fn>)

I can’t post the actual source, but all processPostedMessages does is

MSG msg;
while (PeekMessage(&msg, NULL, 0 , 0, PM_REMOVE)) then
(
MAXScript_interface->TranslateAndDispatchMAXMessage(msg);
)


#17

max 2010 doesn’t have processPostedMessages… I don’t know how can it help. Probably I can call something to show the system that the max is busy. But it’s slow down my calculations. Any window messages slow down everything dramatically.

The hanging issue is all about Window Ghosting feature which was supported by MAX since version 2010. It causes problems. Not just hanging on long calculations. I have problems with some WPF controls (resizing), .NET transparent controls… So maybe it’s a cheating but I put DisableProcessWindowsGhosting() on startup and don’t see any problems anymore.


#18

So how actually code is looks like?


#19
fn DisableProcessWindowsGhosting =
    (
        if classof (dotnet.GetType "DisableWindowsGhosting")!=dotNetObject do
        (
            local source = StringStream ("
                using System.Runtime.InteropServices;

    public class DisableWindowsGhosting
    {
        [DllImport(\"user32.dll\")]
        public static extern bool DisableProcessWindowsGhosting();
    }")

            compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
            compilerParams.ReferencedAssemblies.Add("System.dll");
            compilerParams.GenerateInMemory = on
            csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
            compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source as String)
            flush source
            close source
            if (compilerResults.Errors.Count > 0 ) then
            (
                local errs = stringstream ""
                for i = 0 to (compilerResults.Errors.Count-1) do
                (
                    local err = compilerResults.Errors.Item[i]
                    format "Error:% Line:% Column:% %
" err.ErrorNumber err.Line err.Column err.ErrorText to:errs
                )
                format "%
" errs
                undefined
            )
            else
            (
                compilerResults.CompiledAssembly.CreateInstance "DisableWindowsGhosting"
            )
        )
    )

DisableWindowsGhosting =     DisableProcessWindowsGhosting()
    
DisableWindowsGhosting.DisableProcessWindowsGhosting()

in 3ds max below 2011 version you can use (dotnetClass “Application”). doEvents ()
instead windows.processPostedMessages ()


#20

Thank you Track!

in 3ds max below 2011 version you can use (dotnetClass “Application”). doEvents () instead windows.processPostedMessages ()

What advantages of use (dotnetClass “Application”).doEvents () instead windows.processPostedMessages()?