我有一个C#应用程序,我在其中生成多个线程。我使用的是.NET框架4.7.1。在这些线程中,工作被执行,这项工作可以执行用户定义的脚本函数。我使用ClearScript作为脚本引擎,为了解决这个问题,我使用了VBScriptEngine。下面是一个演示我的问题的示例应用程序:
static VBScriptEngine vbsengine = new VBScriptEngine();
static void Main(string[] args)
{
for (int i=0;i<4000;i++)
{
Thread t = new Thread(Program.ThreadedFunc);
t.Start(i);
}
Console.ReadKey();
}
static void ThreadedFunc(object i)
{
Console.WriteLine(i + ": " + vbsengine.Evaluate("1+1"));
}在because ()函数上,我得到以下错误:System.InvalidOperationException:‘调用线程无法访问这个对象,因为另一个线程拥有它。
据我所知,ClearScript已经实现了线程关联,生成的线程不能访问全局定义的引擎。那我的选择是什么?为每个新线程创建一个新的ClearScript实例?这似乎非常浪费,并将造成大量开销-我的应用程序将需要处理成千上万的线程。我继续尝试了这种方法--尽管它确实起作用了(一段时间)--最终得到了一个错误。下面是我的示例应用程序的修订版:
static void Main(string[] args)
{
for (int i=0;i<4000;i++)
{
Thread t = new Thread(Program.ThreadedFunc);
t.Start(i);
}
Console.ReadKey();
}
static void ThreadedFunc(object i)
{
using (VBScriptEngine vbsengine = new VBScriptEngine())
{
Console.WriteLine(i + ": " + vbsengine.Evaluate("1+1"));
}
}在新的VBScriptEngine()调用中,我现在开始得到:VBScriptEngine“没有足够的存储空间来处理这个命令”。
我不太清楚是什么导致了这条消息,因为应用程序占用的内存不多。
我意识到这个示例应用程序正在一次启动所有线程,但是我的完整应用程序确保只有4个线程正在运行,并且在一段时间后我仍然会收到这条消息。我不知道为什么,但我也无法摆脱这条消息-即使在重新启动应用程序和Visual之后。对造成这一信息的原因稍作澄清将是有用的。
所以我的问题是--如果我只需要一次运行4个线程--我可以创建4个VBScriptEngine实例并为每个新线程调用重用它吗?或者仅仅是主线程上的一个VBScriptEngine实例,而每个新线程只是共享它?
发布于 2018-05-08 18:59:28
使用来自一些帮助团队的ClearScript,我能够让我的示例应用程序在每个线程中只使用一个专用的引擎实例即可工作。诀窍是首先使用自己的线程创建所有必要的引擎,然后在我的循环中使用Dispatcher.Invoke()调用线程函数。下面是使用这种方法更新的示例应用程序:
static void Main(string[] args)
{
var vbengines = new VBScriptEngine[Environment.ProcessorCount];
var checkPoint = new ManualResetEventSlim();
for (var index = 0; index < vbengines.Length; ++index)
{
var thread = new Thread(indexArg =>
{
using (var engine = new VBScriptEngine())
{
vbengines[(int)indexArg] = engine;
checkPoint.Set();
Dispatcher.Run();
}
});
thread.Start(index);
checkPoint.Wait();
checkPoint.Reset();
}
Parallel.ForEach(Enumerable.Range(0, 4000), item => {
var engine = vbengines[item % vbengines.Length];
engine.Dispatcher.Invoke(() => {
ThreadedFunc(new myobj() { vbengine = engine, index = item });
});
});
Array.ForEach(vbengines, engine => engine.Dispatcher.InvokeShutdown());
Console.ReadKey();
}
static void ThreadedFunc(object obj)
{
Console.WriteLine(((myobj)obj).index.ToString() + ": " + ((myobj)obj).vbengine.Evaluate("1+1").ToString());
}
class myobj
{
public VBScriptEngine vbengine { get; set; }
public int index { get; set; }
}https://stackoverflow.com/questions/50218834
复制相似问题