Notifications
Clear all

[Closed] Background worker updating meshes

can anyone give me a real profit of the using the background worker in max scripting?

  • nonblocking UI for scripts that take longer than 5-10 seconds.

i would like to know what kind of magic you wish from the background worker.

  • documentation, so we know what to expect
  • stability, so we can write code that won’t crash max

denisT, I’ve already refactored an unreleased script of mine to use the background worker. The script I’m referring to merges in max characters with biped animations applied. The script used to lock up max’s UI while it was merging in many characters, which causes confusion to users as they think max is not responding. Now, the script merges one character at a time using a background thread until the number of characters to merge is reached. This way, I can still work in 3dsmax while the background worker updates the scene. However, this background worker merging in maxfiles does sometimes crash max.

The same idea could be applied to kilad’s ghosttown – merging in .3ds or .max files in the background to build a city, instead of loading everything at once.

You could use the background worker to check a file directory for new files. If new files are found, you could merge them in, or alert the user that new assets are available.

I could go on, but I cannot predict all the potential uses of the background worker.

i’ve really played with the background worker. and i have a conclusion…
before i tell it… what was it wished?

What’s your conclusion? I’ve been playing with the background worker as well and would like to compare notes. What did you find?

^
That’s what my thoughts are on it more or less. I wouldn’t use it to do the geo stuff I did in my test video, unless it was going to take a really long time and I needed to break it up somehow.

I guess u could possibly split up geo into “buckets” of verts, and process a chunk, refresh so they know its going and can do other stuff, and let it keep going. I’m not sure how stable this would be/ if it would actually work, but it’s an idea.

I use asynchronous loading on some of my tools for images, but I do that through C#, which is sort of the same thing I suppose. I can start loading images and do other work while its going, or even interact with the already loaded images while the other ones go.

Guys,
this is an absolutely different story. The background worker is not a solution. Max freezes on long script operations because max developers following some weird logic supported the Window Ghosting. Which is definitely wrong for this kind of applications.
Since you put


  (
  	source = ""
  	source += "using System;
"
  	source += "using System.Runtime.InteropServices;
"
  	source += "class WindowsGhosting
"
  	source += "{
"
  	source += "	[DllImport(\"user32.dll\")]
"
  	source += "	public static extern void DisableProcessWindowsGhosting();
"
  	source += "}
"
  
  	csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
  	compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
  
  	compilerParams.GenerateInMemory = on
  	compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)

  	assembly = compilerResults.CompiledAssembly
  	windowsGhosting = assembly.CreateInstance "WindowsGhosting"
  	windowsGhosting.DisableProcessWindowsGhosting()
  )
  

in MAX Startup, it solves the problem

oops… i was not the first…

editted

Some minor bug was fixed… One not important line was accidentally wiped

Disabling Windows Ghosting makes the background worker thread waaaaay more stable. I don’t even need the with redraw off ( ) context anymore. I guess the ghosting could of been causing max to crash when the background worker threads processing time exceeded 5-10 seconds. Use plastic’s example code, denisT’s example code threw an error for me (Unknown property: “CompiledAssembly” in undefined).

Here are some race condition test scripts:
Race 1:

(	--is there a race condition between two threads operating on the same max node?	
 	local myBox = box() --create a box()
 	--create an array, fill the array with references to the box
 	local myArray = #(myBox, myBox, myBox, myBox, myBox, myBox, myBox, myBox, myBox, myBox) 
 
 	fn bkgWrkr =
 	(	--randomize the box position in a background thread
 		for i=1 to myArray.count do
 			(myArray[i].pos = [(random -200 200),(random -200 200),0])
 	)
 	fn foregroundWrkr =
 	(	--randomize the box position in a foreground thread
 		for i=1 to myArray.count do
 			(myArray[i].pos = [(random -200 200),(random -200 200),0])
 	)
 	
 	MainThread = dotnetobject "CSharpUtilities.SynchronizingBackgroundWorker"
 	dotNet.addEventHandler MainThread "DoWork" bkgWrkr
 	MainThread.RunWorkerAsync()
 	foregroundWrkr()
 )

Race 2:

(	--which thread finishes last?
 	local myBox = box() --create a box()
 	--create an array, fill the array with references to the box
 	local myArray = #(myBox, myBox, myBox, myBox, myBox, myBox, myBox, myBox, myBox, myBox) 
 
 	fn bkgWrkr =
 	(	--move the box position in a background thread
 		for i=1 to myArray.count do
 			(myArray[i].pos = [0,100,0])
 	)
 	fn foregroundWrkr =
 	(	--move the box position in a foreground thread
 		for i=1 to myArray.count do
 			(myArray[i].pos = [0,0,0])
 	)
 	
 	MainThread = dotnetobject "CSharpUtilities.SynchronizingBackgroundWorker"
 	dotNet.addEventHandler MainThread "DoWork" bkgWrkr
 	MainThread.RunWorkerAsync()
 	foregroundWrkr()
 )	--in this example, the bkgWrkr always finishes last (for me)

Race 3:

(	--which thread finishes last?
 	local myBox = box() --create a box()
 	--create an array, fill the array with references to the box
 	local myArray = #(myBox, myBox, myBox, myBox, myBox, myBox, myBox, myBox, myBox, myBox) 
 
 	fn bkgWrkr =
 	(	--move the box position in a background thread
 		for i=1 to myArray.count do
 			(myArray[i].pos = [0,100,0])
 	)
 	fn foregroundWrkr =
 	(	--move the box position in a foreground thread
 		for i=1 to myArray.count do
 			(
 				for j=1 to 10000 do (j+=1)
 				myArray[i].pos = [0,0,0]
 			)
 	)
 	
 	MainThread = dotnetobject "CSharpUtilities.SynchronizingBackgroundWorker"
 	dotNet.addEventHandler MainThread "DoWork" bkgWrkr
 	MainThread.RunWorkerAsync()
 	foregroundWrkr()
 )	--in this example, the foreground worker finishes last

On this thread, Kameleon wonders if the fast attach algorithm tyson described could be split between two or more threads. This is an interesting challenge.

I propose that we (cgtalk maxscripters) have a series of background worker thread challenges, where we explore whats possible with the background worker. Kameleon’s question could be the first challenge topic. What do you think?

it’s fixed now

Edit: Oops, didn’t see page 2 of the thread, so this is probably an outdated comment.

Tested the latest ‘20 boxes’ script in MaxDesign 2012 x64, initial run worked without a crash or error. It does ‘pause’ the nitrous viewport as the new box is added. Other than that, I could interact fine, even was able to create a teapot across multiple box creations and no error. Then I pushed it further and tried adding a modifier and editing the teapot while the bg workers were going. Initially it worked, but moving vertices seemed to interrupt the boxes from being created, as I pushed that further, and just continually moved vertices around for several seconds, it then eventually crashed Max, though interestingly it seemed like the background workers were still coming back and adding boxes as Max was in the process of crashing!

 PEN

Thought that I would resurrect this thread. I’m testing on my lap top running 32 bit in Max 2012 and I’m not able to get any of the test code running here without crashing Max and even a blue screen once.

Any one having similar issues?

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

the issue indicates that your system working right max DOESN’T support any gc or ui related multi-threading operation. it has to crash!

 PEN

I don’t follow you Denis. I gather from this thread that others have it working. Is that incorrect to assume?

Or is the backgroundworker always unstable? I did some tests at one point that worked but haven’t really needed it until now.

I think that if a method causes crash it doesn’t work. no one on this forum could make the backgroundworker works. Because it’s not possible.
you can create one – two – twenty… nodes but sooner or later it will crash anyway. We can’t talk about any stability there. It’s just not working.

But it doesn’t mean that we can’t use backgroundworker. You can do some things, but without touching GC, undo, and max UI (including viewport redraw).

Why do you need the backgroundworker?

 PEN

What about updating a dotNet UI built in Max Script?

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

yes, you can.

Page 3 / 5