Notifications
Clear all

[Closed] pausing maxscript execution without UI lock

 lo1

I’m sure someone can help you with a better design if you post code which actually represents what you’re trying to do.

 lo1

Yes but you still have to create a form for it. A System.Windows.Forms.Timer needs to be associated with a form to run.

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

no. it works without parent form as well

t = dotnetobject "Timer"
t.interval = 1

fn executeJob s e = 
(
	s.Stop()
	print "job done"
)
dotnet.addEventHandler t "Tick" executeJob
t.Start()
 lo1

Nice to know. The documentation suggests otherwise.

 lo1

It seems you can only start the timer from the UI thread. If you try to call Start() or set Enabled = on from a background thread, the event is never raised.

t = dotnetobject "Timer"
t.interval = 1

fn executeJob s e = 
(
	s.Stop()
	print "job done"
)
dotnet.addEventHandler t "Tick" executeJob

fn bgWork = t.Start()
bgw = dotnetObject "System.ComponentModel.BackgroundWorker"
dotnet.addEventHandler bgw "DoWork" bgWork
bgw.RunWorkerAsync()

you have to pass timer as object to worker. i wrote my worker class with tag property

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0
fn createBackgroundWorkerAssembly =
 (		
 	source  = ""
 	source += "using System;
"
 	source += "using System.ComponentModel;
"
 	source += "public class CustomBackgroundWorker : BackgroundWorker
"
 	source += "{
"
 	source += "	private Object _tag;
"
 	source += "	public Object Tag
"
 	source += "	{
"
 	source += "		get { return _tag; }
"
 	source += "		set { _tag = value; }
"
 	source += "	}
"
 	source += "}
"
 	
 	local csharpProvider = dotnetobject "Microsoft.CSharp.CSharpCodeProvider"
 	local compilerParams = dotnetobject "System.CodeDom.Compiler.CompilerParameters"
 	compilerParams.ReferencedAssemblies.addRange #("System.dll")
 	compilerParams.GenerateInMemory = on
 	local compilerResults = csharpProvider.CompileAssemblyFromSource compilerParams #(source)
 	compilerResults.CompiledAssembly
 )
 bass = createBackgroundWorkerAssembly()
 (
 	t = dotnetobject "Timer"
 	t.interval = 1
 	t.enabled = off
 
 	fn executeJob s e =
 	(
 		s.Stop()
 		print "job done"
 	)
 	dotnet.addEventHandler t "Tick" executeJob
 	t.Start()
 
 	fn onDoWork s e = 
 	(
 		s.tag.enabled = on
 		print "work done"
 	)
 	bw = bass.CreateInstance "CustomBackgroundWorker"
 	bw.tag = t
 	dotnet.addEventHandler bw "DoWork" onDoWork
 	bw.RunWorkerAsync()
 	bw.Dispose()
 )

timer can be local in this case

all is much easier after i thought a little more:

(
 	t = dotnetobject "Timer"
 	t.interval = 1
 	t.enabled = off
 
 	fn executeJob s e =
 	(
 		s.enabled = off
 		print "job done"
 	)
 	dotnet.addEventHandler t "Tick" executeJob
 	t.Start()
 
 	fn onDoWork s e = 
 	(
 		e.Argument.enabled = on
 		print "work done"
 	)
 	bw = dotnetObject "System.ComponentModel.BackgroundWorker"
 	dotnet.addEventHandler bw "DoWork" onDoWork
 	bw.RunWorkerAsync t
 	bw.Dispose()
 )  
 lo1

except that “job done” will always run after “work done”. There is no way to wait for ‘executeJob’ to finish.

1 Reply
(@denist)
Joined: 11 months ago

Posts: 0

you can… you can tag worker for timer and timer can check worker’s progress

windows.processPostedMessages() might help you in what you are trying to do.

Recenctly, I was happy to find this link about it.

 lo1

I find the rollout timer method cleaner and simpler

@Gumtoo

that was what I was searching for…

I put together a small dirty sample which is creating a box, hanging in the do while loop until the continue button is pressed which allows me to stop at this point as long as I would without locking the UI.

The only drawback is that one thread is blocked by the loop but for the meantime I will live with that solution…

thanks!

(
global continuePause = true

rollout diag ""
(
	button continue_button "continue"
	
	on continue_button pressed do
	(
		"print stop"
		
		continuePause = false
		destroydialog diag
	)
)
	
box()

redrawViews() 

createdialog diag

do
(		
	windows.processPostedMessages()		
)
while(continuePause == true)

cylinder()

)

@lo

well, I can’t upload my whole program since it contains more than 5000 lines of code which is also why I don’t want to rearchitecture everything.

the best simplification of what my problem looks like was my last attempt with the loop…

I definitely think that your approach is useful when you start from scratch but I for me the requirements changed during developement which is why I did not code the architecture in the way which would be required for your approach…

Page 2 / 2