C# ActiveX对象和.NET垃圾收集器
我在.net中遇到了多线程问题。使用以下代码:C# ActiveX对象和.NET垃圾收集器,c#,multithreading,C#,Multithreading,我在.net中遇到了多线程问题。使用以下代码: class Program { private static ManualResetEvent[] resetEvents; private void cs(object o) { int xx = 0; while (true) { xx++; System.Xml.XmlDocument document = new Sys
class Program
{
private static ManualResetEvent[] resetEvents;
private void cs(object o)
{
int xx = 0;
while (true)
{
xx++;
System.Xml.XmlDocument document = new System.Xml.XmlDocument();
document.Load("ConsoleApplication6.exe.config");
MSScriptControl.ScriptControlClass s =
newMSScriptControl.ScriptControlClass();
s.Language = "JScript";
object res = s.Eval("1+2");
Console.WriteLine("thread {0} execution {1}" , o , xx);
System.Threading.Thread.Sleep(5000);
}
}
static void Main(string[] args)
{
Program c = new Program();
for (int i = 0; i < 1000; i++)
{
System.Threading.Thread t = new System.Threading.Thread(
new System.Threading.ParameterizedThreadStart(c.cs));
t.Start((object)i);
}
}
}
类程序
{
专用静态手动重置事件[]重置事件;
私人文书主任(对象o)
{
int xx=0;
while(true)
{
xx++;
System.Xml.XmlDocument document=new System.Xml.XmlDocument();
Load(“ConsoleApplication6.exe.config”);
MSScriptControl.ScriptControlClass s=
newMSScriptControl.ScriptControlClass();
s、 Language=“JScript”;
对象res=s.Eval(“1+2”);
WriteLine(“线程{0}执行{1}”,o,xx);
系统线程线程睡眠(5000);
}
}
静态void Main(字符串[]参数)
{
程序c=新程序();
对于(int i=0;i<1000;i++)
{
System.Threading.Thread t=新的System.Threading.Thread(
新的System.Threading.ParameterizedThreadStart(c.cs));
t、 启动((对象)i);
}
}
}
执行此代码时,它会在几分钟后崩溃。为什么它会崩溃?如何防止崩溃?您将启动1000个线程。这是1000 MB的堆栈空间加上线程创建的所有对象。我猜你的记忆快用完了。你想实现什么?创建比处理器核心更多的线程几乎没有意义。b/c应用程序将花费大量时间切换上下文,并且你将看不到任何性能提升。同时运行的唯一线程数等于您的计算机拥有的内核数。为什么这必须用1000个线程来完成?(显然,我假设你没有1000核的机器)鉴于提供的代码,这个应用程序的某些方面可能并不明显。也就是说,我无法重现崩溃,但我可以运行大量的内存使用量(29“xx++”s时为160MB) 我怀疑ScriptControlClass在内存中保持活动状态。虽然可能有更好的方法解决这个问题,但通过添加以下内容,我能够将内存保持在一致的60-70MB:
Console.WriteLine("thread {0} execution {1}" , o , xx);
s = null;
更新
我对这段代码在内存方面也有类似的结果,但是下面的代码稍微快一点。几分钟后,当
xx<30
更改回true
时,内存使用量为一致的51MB
class Program
{
private static ManualResetEvent[] resetEvents;
[ThreadStatic]
static ScriptControlClass s;
private void cs(object o)
{
int xx = 0;
if (s == null)
{
s = new ScriptControlClass();
}
/* you should be able to see consistent memory usage after 30 iterations */
while (xx < 30)
{
xx++;
//Unsure why this is here but doesn't seem to affect the memory usage
// like the ScriptControlClass object.
System.Xml.XmlDocument document = new System.Xml.XmlDocument();
document.Load("ConsoleApplication6.exe.config");
s.Language = "JScript";
object res = s.Eval("1+2");
Console.WriteLine("thread {0} execution {1}", o, xx);
System.Threading.Thread.Sleep(5000);
}
s = null;
}
static void Main(string[] args)
{
Program c = new Program();
for (int i = 0; i < 1000; i++)
{
System.Threading.Thread t = new System.Threading.Thread(
new System.Threading.ParameterizedThreadStart(c.cs));
t.Start((object)i);
}
}
}
类程序
{
专用静态手动重置事件[]重置事件;
[线程静态]
静态脚本控件类;
私人文书主任(对象o)
{
int xx=0;
如果(s==null)
{
s=新的ScriptControlClass();
}
/*您应该能够在30次迭代后看到一致的内存使用情况*/
而(xx<30)
{
xx++;
//不确定为什么会出现这种情况,但似乎不会影响内存使用
//就像ScriptControlClass对象一样。
System.Xml.XmlDocument document=new System.Xml.XmlDocument();
Load(“ConsoleApplication6.exe.config”);
s、 Language=“JScript”;
对象res=s.Eval(“1+2”);
WriteLine(“线程{0}执行{1}”,o,xx);
系统线程线程睡眠(5000);
}
s=零;
}
静态void Main(字符串[]参数)
{
程序c=新程序();
对于(int i=0;i<1000;i++)
{
System.Threading.Thread t=新的System.Threading.Thread(
新的System.Threading.ParameterizedThreadStart(c.cs));
t、 启动((对象)i);
}
}
}
更新2
我在谷歌上找不到任何关于在多线程环境中使用ScriptControlClass的信息 @Brian:哇。他实际上用简单的方法创建了StackOverFlow:)@Joel:我怀疑OP是否得到了StackOverflowException,因为代码没有耗尽堆栈。可能是OutOfMemoryException。如何计算堆栈空间中的1000MB?我计数(4(
o
)+4(xx
)+4(document
)+4(s
)+4(res
)+4(返回地址))*1000字节=6KB。@Konrad:每个线程在.NET中每个默认值都有1MB的堆栈(除非是ASP应用程序,在这种情况下,默认值是256KB)。代码会创建1000个线程,因此进程会为1000 MB的堆栈保留空间。@Konrad,这是因为默认情况下每个线程都有1 MB的堆栈,并且有1000个堆栈。