Notifications
Clear all

[Closed] superClassOf in multithreading

Have you ever tried to use the function superClassOf in multithreading?

Several days I was investigating how to make my scripter faster by using multithreading, but Max crashes everytime if I use 2 threads. I made completely different variables and functions for every thread, but still 3D max crashes. I tried step by step to find out what’s the reason, the reason was this line when using simultaniously

if superClassOf prop == Material then …

both functions and variables are completelly different.
Is there a way to replace the function superClassOf with anything else, I need to find out if prop is a material or not.

ClassOf does not fit.

37 Replies

I don’t know if this will works but try with


isKindOf

the fanny thing is that I use

IsKindOf

in the same script a little bellow, It really doesn’t crash max as superClassOf, but another problem arose that kills max in multithreading. I came to the conclusion that the scanning of two different materials in different threads is impossible anyway

w1 = undefined
 w2 = undefined
 
 fn work1 = (
 	
 	w1 = for i=1 to 24 collect superclassof meditmaterials[i]	
 	
 )
 
 fn work2 = (
 	
 	w2 = for i=1 to 24 collect ( iskindof meditmaterials[i] material )	
 	
 )
 
 mythreads = #()
 myThreads[1] = dotNetObject "CSharpUtilities.SynchronizingBackgroundWorker"
 myThreads[2] = dotNetObject "CSharpUtilities.SynchronizingBackgroundWorker"
 
 dotnet.addEventHandler myThreads[1] "DoWork" work1
 dotnet.addEventHandler myThreads[2] "DoWork" work2
 
 myThreads[1].runworkerasync()
 myThreads[2].runworkerasync()

max2014x64 works fine

yes, this is very simple, but I wanted to use multithreading for a deep material scanning like this code:


 (
 	struct matDef (mat, path)
  
 	local getSubmats, subMats = #()
  
 	fn capitalizeFirst str =
 		toUpper str[1] + subString str 2 -1
  
 	fn formatName mat index: =
 		if isKindOf mat TextureMap OR index == unsupplied then
 			capitalizeFirst ((classOf mat) as string) + "\\"
 		else (substituteString (getSubTexmapSlotName mat index) " map" "") + "\\"
  
 	fn getSubmatsRecurse mat matInst path:"" =
 		for propName in (getPropNames mat) do
 		(
 			local prop = getProperty mat propname
 			if superClassOf prop == Material then
 				getSubmats prop path:path \
 					format:(capitalizeFirst (propname as string) + "\\" + formatName prop)
 			else if classOf prop == ArrayParameter do
 				for sub = 1 to prop.count where superClassOf prop[sub] == Material do 
 					getSubmats prop[sub] path:path \
 						format:("Map" + sub as string + "\\" + formatName prop[sub])
 		)
  
 	fn getSubmats mat path:"" format:"" =
 	(
 		local matInst = matDef mat:mat path:(path + format)
 		append subMats matInst
 		getSubmatsRecurse mat matInst path:(path + format)
 		subMats
 	)
  
 	fn recurseMat mat path:"" =
 		for i = 1 to (getNumSubTexmaps mat)
 			where (local map = getSubTexmap mat i) != undefined do
 				if getNumSubTexmaps map > 0 then
 					recurseMat map path:(path + formatName mat index:i)
 				else if isKindOf map BitmapTexture do
 				(
 					format "Texture: %
" map.filename
 					format (path + formatName mat index:i + "

") 
 				)
  
 	local current_mtl = mEdit.getCurMtl()
 	local subMatInsts = getSubmats current_mtl
  
 	format "
Base material: %

" (classOf current_mtl)
 	for matInst in subMatInsts do
 		recurseMat matInst.mat path:("MAP TREE: " + matInst.path)
 
 

swordsplayer helped me one day with this code, and it’s working just fine for my needs, but in big scenes with many materials and textures it takes long to calculate. It gives me the map tree that is very important for me to be displayed.

i think the problem is the using of recursion in another than main thread…
probably you have to define all recursive functions inside a function which you call with a BackgroundWorker’s work

Denis, you’re right. After changing SuperClassOf with isKindOf, the next bottle neck was the recursion. But I think, what I need is impossible to do without recursion and as a result is impossible to do in multithreading.

Denis, I have just noticed what you said, to define all recursive functions inside a function. How could I read this and not notice ))
Please tell me, how to do that? Please…

you have to define recursive function inside “work” function:


ww = #(#(),#())

meditmaterials[1] = multimaterial numsubs:(random 60 100)
meditmaterials[2] = multimaterial numsubs:(random 60 100)

fn work1 s e = 
(
	fn collectMats mat mats:#() fun: = 
	(
		if iskindof mat Material and (appendifunique mats mat) do for k=1 to getNumSubMtls mat where (m = getSubMtl mat k) != undefined do
		(
			if (appendifunique mats m) do fun mat mats:mats fun:fun
		)
		ok
	)
	collectmats meditmaterials[1] mats:ww[1] fun:collectmats
	s.Dispose()
)
fn work2 s e = 
(
	fn collectMats mat mats:#() fun: = 
	(
		if iskindof mat Material and (appendifunique mats mat) do for k=1 to getNumSubMtls mat where (m = getSubMtl mat k) != undefined do
		(
			if (appendifunique mats m) do fun mat mats:mats fun:fun
		)
		ok
	)
	collectmats meditmaterials[2] mats:ww[2] fun:collectmats
	s.Dispose()
)

 
mythreads = #()
myThreads[1] = dotNetObject "CSharpUtilities.SynchronizingBackgroundWorker"
myThreads[2] = dotNetObject "CSharpUtilities.SynchronizingBackgroundWorker"
 
dotnet.addEventHandler myThreads[1] "DoWork" work1
dotnet.addEventHandler myThreads[2] "DoWork" work2
 
myThreads[1].runworkerasync()
myThreads[2].runworkerasync()

while (myThreads[1].IsBusy or myThreads[2].IsBusy) and (not keyboard.escPressed) do ()
format "1 done:(%) - %
" ww[1].count ww[1]
format "2 done:(%) - %
" ww[2].count ww[2]

both workers can use the same event function. in this case you have to pass specific settings (where or what to search for example) with a worker. i’ve showed how to extend BackgroundWorker with adding tag property for example.

Page 1 / 4