Hi Tom,
Unfortunately memory management can get tricky with long-running scripts.
When you pass a script object into managed code, ClearScript creates a managed proxy for it. The proxy holds a strong reference to its target, so the script object can't be garbage-collected until the proxy is disposed or finalized.
Therefore one way to avoid the leak is to dispose the proxy when you're done with it:
Another possibility is to invoke managed garbage collection and finalization before calling
An unfortunate wrinkle with this approach is that you can no longer call
Thanks, and good luck!
Unfortunately memory management can get tricky with long-running scripts.
When you pass a script object into managed code, ClearScript creates a managed proxy for it. The proxy holds a strong reference to its target, so the script object can't be garbage-collected until the proxy is disposed or finalized.
Therefore one way to avoid the leak is to dispose the proxy when you're done with it:
publicvoid doSomething(dynamic foo) { var disposable = foo as IDisposable; if (disposable != null) { disposable.Dispose(); } }
ScriptEngine.CollectGarbage()
:publicvoid garbageCollect() { GC.Collect(); GC.WaitForPendingFinalizers(); // [...] m_engine.CollectGarbage(true); // [...] }
garbageCollect()
from script code. Proxy finalization requires help from the script engine, which is locked during script execution, so the GC.WaitForPendingFinalizers()
call causes a deadlock. Instead, you'll have to restructure your code like this:engine.Execute(@"var count = 0"); while (true) { engine.Execute(@" while (true) { if (++count % 10000 == 0) { break; } obj = { a: ""b"", c: ""d"" }; nativeBridge.doSomething(obj); } "); p.garbageCollect(); }