BackgroundWorker DoWork线程的堆栈大小是多少?有办法改变吗?

时间:2019-06-05 09:20:24

标签: c# multithreading .net-4.5 backgroundworker stack-size

对于C#主程序,我知道堆栈大小为1 MB(32位和任意位)或4 MB(64位),请参见Why is stack size in C# exactly 1 MB?

BackgroundWorker DoWork线程的默认堆栈大小是多少?

除了创建另一个线程,是否有一种方法可以更改BackgroundWorker DoWork线程的堆栈大小,如下例所示:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{   
    Thread thread = new Thread(delegate()
    {
        // do work with larger stack size
    }, 8192 * 1024);
    thread.Start();
    thread.Join();
}

我使用BackgroundWorker是因为我有一个Windows Forms应用程序,我在DoWork事件中进行了一些计算。我这样做是因为我想向GUI报告状态行,并且希望用户可以取消计算。

由于我正在调用英特尔MKL LAPACKE_dtrtri(这是高度递归的),因此我得到了堆栈溢出错误,请参见http://www.netlib.org/lapack/explore-html/df/d5c/lapacke__dtrtri_8c_source.html

以下代码显示了我如何称呼英特尔MKL:

public static double[,] InvTriangularMatrix(double[,] a, bool isupper)
{
    int n1 = a.GetLength(0);
    int n2 = a.GetLength(1);
    if (n1 != n2) throw new System.Exception("Matrix must be square");
    double[,] b = Copy(a);
    int matrix_layout = 101; // row-major arrays
    char uplo = isupper ? 'U' : 'L';
    char diag = 'N';
    int lda = Math.Max(1, n1);
    int info = _mkl.LAPACKE_dtrtri(matrix_layout, uplo, diag, n1, b, lda);
    if (info > 0) throw new System.Exception("The " + info + "-th diagonal element of A is zero, A is singular, and the inversion could not be completed");
    if (info < 0) throw new System.Exception("Parameter " + (-info) + " had an illegal value");
    return b;
}

[DllImport(DLLName, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, SetLastError = false)]
internal static extern int LAPACKE_dtrtri(
    int matrix_layout, char uplo, char diag, lapack_int n, [In, Out] double[,] a, int lda);

在我的InvTriangularMatrix事件中调用了DoWork。当我未设置堆栈大小时,我在LAPACKE_dtrtri函数中收到了堆栈溢出错误。

矩阵的大小可以在1000 x 1000到100000 x 100000的数量级。如果矩阵大于65535 x 65535,请参见2d-Array with more than 65535^2 elements --> Array dimensions exceeded supported range

1 个答案:

答案 0 :(得分:0)

BackgroundWorker DoWork事件中的堆栈大小与主线程相同。

教授:

例如,将构建后事件中的堆栈大小设置为8 MB:

"$(DevEnvDir)..\..\VC\bin\editbin.exe" /STACK:8388608 "$(TargetPath)"

然后使用以下代码要求堆栈大小:

[DllImport("kernel32.dll")]
internal static extern void GetCurrentThreadStackLimits(out uint lowLimit, out uint highLimit);


public static uint GetStackSize()
{
    uint low, high;
    GetCurrentThreadStackLimits(out low, out high);
    return high - low;
}

在两种情况下,在主程序和GetStackSize事件中使用DoWork都会返回8 MB或使用EDITBIN /STACK指定的任何值。