[Closed] pausing maxscript execution without UI lock
I’m sure someone can help you with a better design if you post code which actually represents what you’re trying to do.
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.
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()
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
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()
)
except that “job done” will always run after “work done”. There is no way to wait for ‘executeJob’ to finish.
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…