我有一个后续问题 What is the stack size of a BackgroundWorker DoWork Thread? Is there way to change it?
我应该使用以下构建后事件增加主程序的堆栈大小:
"$(DevEnvDir)..\..\VC\bin\editbin.exe" /STACK:8388608 "$(TargetPath)"
还是我应该将递归代码块封装在具有更大堆栈大小的新线程中?
Thread thread = new Thread(delegate()
{
// do work with larger stack size
}, 8192 * 1024);
thread.Start();
thread.Join();
具有大量递归的代码来自英特尔MKL的LAPACKE_dtrtri函数,我在DLLImport
上进行了调用。因此,我无法更改此代码。我可以更改堆栈大小以避免堆栈溢出错误。
为我的主程序分配更大的堆栈大小有什么缺点?
为该计算创建具有更大堆栈大小的新线程的缺点是什么?
哪种解决方案更好?
合理的堆栈大小是多少? 8 MB,16 MB,32 MB或64 MB(例如MATLAB)?该程序在具有至少16 GB RAM(最大256 GB)的计算机上运行。
注意:对于我的应用程序的99%,默认的堆栈大小4 MB(64位)就足够了,但是其他1%的用户使用的是外部代码,该代码具有高度递归性。
答案 0 :(得分:0)
- 哪种解决方案更好?
- 哪种解决方案更好?
在构建后事件中使用editbin
的第一种方法在使用强名称密钥对程序集进行签名时失败。使用editbin
更改了程序集后,对签名程序集的验证将失败。 sn.exe -v assembly.exe
将返回Failed to verify assembly -- Strong name validation failed ...
另请参见:
使用AfterCompile
事件并退出程序集是一种解决方法(我现在正在使用)。项目文件应包含以下几行:
<Target Name="AfterCompile">
<Exec Command="
"$(DevEnvDir)..\..\VC\bin\editbin.exe" /STACK:16777216 "$(ProjectDir)obj\$(ConfigurationName)\$(TargetFileName)"
"$(FrameworkSDKDir)bin\NETFX 4.5.1 Tools\sn.exe" -Ra "$(ProjectDir)obj\$(ConfigurationName)\$(TargetFileName)" "$(SolutionDir)\STRONGNAME.snk"
" />
</Target>
<PropertyGroup>
<PostBuildEvent>REM "See AfterCompile for stack size and resigning"</PostBuildEvent>
</PropertyGroup>
当我阅读以下答案时,我意识到了编译后事件:https://stackoverflow.com/a/22617361/7556646
第二种方法,但对于hole程序,不仅对于递归代码块,都将如下所示:
static class Program
{
[STAThread]
static void Main(string[] args)
{
Thread thread = new Thread(delegate()
{
Main2(args);
}, 16 * 1024 * 1024);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
}
static void Main2(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(app);
}
}
第二种方法的缺点是BackgroundWorker DoWork事件的堆栈大小仍然是1 MB(32位或任意)或4 MB(64位)。
另请参见:
- 为此计算创建具有更大堆栈大小的新线程的缺点是什么?
- 合理的堆栈大小是多少?
请参阅Hans Passant的评论。