New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using ClearScript inside Threads #53
Comments
Hello @ahoekstra, It's difficult to diagnose your issue without more information, so we'll make a couple of general comments and provide a sample that demonstrates concurrent First, creating thousands of threads is almost always counterproductive. You reserve gigabytes of address space just for stacks, and since most machines don't have thousands of cores, you're likely to get thrashing and resource exhaustion. Thread pools optimize efficiency by carefully controlling thread usage. Unfortunately Windows script engines (JScript/VBScript) have thread affinity, and that makes them fundamentally incompatible with thread pools, as each instance can only run script code on the thread that constructed it. The First, create an array of script engines with dedicated threads: var engines = new VBScriptEngine[Environment.ProcessorCount];
var checkPoint = new ManualResetEventSlim();
for (var index = 0; index < engines.Length; ++index) {
var thread = new Thread(indexArg => {
using (var engine = new VBScriptEngine()) {
engines[(int)indexArg] = engine;
checkPoint.Set();
Dispatcher.Run();
}
});
thread.Start(index);
checkPoint.Wait();
checkPoint.Reset();
} Now you can use var items = Enumerable.Range(0, 10000);
Parallel.ForEach(items, item => {
var engine = engines[item % engines.Length];
engine.Dispatcher.Invoke(() => {
var expr = string.Format("{0} * 2", item);
Console.WriteLine(engine.Evaluate(expr));
});
}); This sample uses simple round-robin engine selection and synchronous dispatching, but more sophisticated approaches are certainly possible. Finally, to terminate the threads and dispose the script engines: Array.ForEach(engines, engine => engine.Dispatcher.InvokeShutdown()); Good luck! |
Thank you! This is a great response and appears to have addressed my question perfectly. Now I get to try and implement this solution into my application! Was time to update to Parallel threading anyways.. |
I have a C# application where I spawn multiple threads. I'm on .NET framework 4.7.1. Inside these threads, work is performed and this work may execute user-defined scripted functions. I am using ClearScript as the scripting engine and for purposes of this question I am using the VBScriptEngine. Here is an sample application demonstrating my problem:
On the Evaluate() function I get the following error: System.InvalidOperationException: 'The calling thread cannot access this object because a different thread owns it.'
I understand ClearScript has implemented thread affinity and a spawned thread cannot access the globally defined engine. So what is my alternative? Create a new instance of ClearScript for each new thread? This seems incredibly wasteful and would create a lot of overhead - my application will need to process thousands of threads. I went ahead and tried this approach anyways - and while it does work (for a while) - end up getting an error. Here's a revised version of my sample app:
On the new VBScriptEngine() call, I now start getting: System.ComponentModel.Win32Exception: 'Not enough storage is available to process this command'.
I'm not really sure what's causing that message as the application isn't taking up a lot of RAM.
I realize this sample application is starting all the threads at once but my full application ensures only 4 threads are running and I still end up getting this message after a while. I don't know why, but I can't get rid of this message either - even after restarting the app and Visual Studio. A little clarity on what's causing this message would be useful.
So my question is - if I only need, say 4 threads, running at once - is there a way I can just create 4 instances of the VBScriptEngine and reuse it for each new thread call? Or even just 1 instance of the VBScriptEngine on the main thread and each new thread just shares it?
The text was updated successfully, but these errors were encountered: