I’m having problems with dotNET and multi threading (BackgroundWorker) inside a Struct.
I’m trying to create a general purpose Struct with various methods etc… to use in my workflow. I started with a method I need now, that takes a current maxFile and packs it externally in WinRAR via the Process class. I wanted to make this operation run in another thread so that I can still use Max while the process is being executed (packing certain large files takes time), however, I bumped into a problem I don’t really know how to deal with.
Here’s a snippet of the struct:
struct duberOps
(
duberPath = @"C:\duber",
sysPath = dotNetClass "System.IO.Path",
process = dotNetClass "System.Diagnostics.Process",
startInfo = dotNetClass "System.Diagnostics.ProcessStartInfo",
MainThread = dotnetobject "CSharpUtilities.SynchronizingBackgroundWorker",
fn runWinRARInBG sender ev =
(
for i = 1 to 10 do print ( "iter: " + (i as string) + " it works!" )
return "SOMETHING"
),
fn compressCurrentSceneFile method:#rar =
(
-- the path to the rar.exe file
local archiverPath = this.sysPath.Combine this.duberPath @"WinRAR\4.01_x64\Rar.exe"
local process = dotNetObject this.process
local startInfo = dotNetObject this.startInfo
-- multithreading support
this.MainThread.WorkerSupportsCancellation = true
this.MainThread.WorkerReportsProgress = true
dotNet.addEventHandler this.MainThread "DoWork" this.runWinRARInBG
if this.MainThread.IsBusy do this.MainThread.CancelAsync()
-- check whether the current file is saved to disk
if maxFileName != "" or maxFilePath != "" do
(
local completeFileName = this.sysPath.Combine maxFilePath maxFileName
if not this.MainThread.IsBusy do this.MainThread.RunWorkerAsync()
)
)
)
duberOps = duberOps()
As you can see, I’m using a similar approach to Lonerobot’s multithreading example. But, when executing the duberOps.compressCurrentSceneFile() function that should trigger the runWinRARInBG() function in another thread via the dotnetobject “CSharpUtilities.SynchronizingBackgroundWorker” object, it only returns undefined. That’s it.
But when I add the dotNet eventHandler to a globally declared function outside that Struct, it runs it without problems.
Am I missing something here? Why isn’t the backgroundWorker triggering the function inside the same struct?
Made a few tweaks, and it is now working here, (the file path change shouldn’t be needful, just changed it to a local, existing path on my machine)
(
struct duberOps
(
duberPath = @"C: est1",
sysPath = dotNetClass "System.IO.Path",
process = dotNetClass "System.Diagnostics.Process",
startInfo = dotNetClass "System.Diagnostics.ProcessStartInfo",
MainThread = dotnetobject "CSharpUtilities.SynchronizingBackgroundWorker",
fn runWinRARInBG sender ev =
(
for i = 1 to 10 do print ( "iter: " + (i as string) + " it works!" )
return "SOMETHING"
),
fn compressCurrentSceneFile method:#rar =
(
-- the path to the rar.exe file
local archiverPath = this.sysPath.Combine this.duberPath @"WinRAR\4.01_x64\Rar.exe"
local process = dotNetObject this.process
local startInfo = dotNetObject this.startInfo
-- multithreading support
this.MainThread.WorkerSupportsCancellation = true
this.MainThread.WorkerReportsProgress = true
dotNet.addEventHandler this.MainThread "DoWork" this.runWinRARInBG
if this.MainThread.IsBusy do this.MainThread.CancelAsync()
-- check whether the current file is saved to disk
if maxFileName != "" or maxFilePath != "" do
(
local completeFileName = this.sysPath.Combine maxFilePath maxFileName
if not this.MainThread.IsBusy do this.MainThread.RunWorkerAsync()
)
)
)
theStructInstance = duberOps()
theStructInstance.runWinRARInBG "" ""
)
…which printed out in the MAXscript Listener,
"iter: 1 it works!"
"iter: 2 it works!"
"iter: 3 it works!"
"iter: 4 it works!"
"iter: 5 it works!"
"iter: 6 it works!"
"iter: 7 it works!"
"iter: 8 it works!"
"iter: 9 it works!"
"iter: 10 it works!"
"SOMETHING"
I didn’t look too closely but it sounds like it could be a garbage collection issue. Try setting the garbage collector (lifetime, or something like that?). Or you can assign things globally to make sure they aren’t garbage collected, like I think you did.
The red flags of garbage collection issues in Max/.NET (where one GC is interferring with the other) are semi-arbitrary crashes (when something is GC’ed “illegally”), and events disappearing.