Parallel.For导致静态函数非null参数变为空

时间:2017-01-30 22:40:43

标签: c# .net

我有一个双重for循环没有问题,但是当我将外部循环转换为Parallel.For时失败,因为调用了这个函数而失败:

NormalizationPoint.CalculateDose( 
     fPixel1, fPixel2, uncompensatedBeams, new Vector3D( xLocation, yLocation, PlaneZ ) );

该函数具有此签名:

 public static double CalculateDose(
    FluencePixel fluencePixel1, FluencePixel fluencePixel2, 
    Beam[] uncompensatedBeams, Vector3D location )

fPixel1,我肯定不是null,在CalculateEstimatedDose(它没有在任何地方设置)的主体中以某种方式变为null。奇怪的是,fPixel2正好被传递。这是完整的代码:

Parallel.For(0, yLength, y =>
{
    for ( int x = 0; x < xLength; x++ )
    {
        double xLocation = ImageData.Origin.X + ( 0.5 + x ) * ImageData.XRes; // offset by half pixel to get center of pixel
        double yLocation = ImageData.Origin.Y + ( 0.5 + y ) * ImageData.YRes;
        Vector3D pixelLocation = new Vector3D( xLocation, yLocation, PlaneZ );
        if (( fPixel1 = fluences[0].GetIntersectingFluencePixel( pixelLocation ) ) != null
            && ( fPixel2 = fluences[1].GetIntersectingFluencePixel( pixelLocation ) ) != null )
        {
            // I added this redundant check just to be SURE it wasn't passed in null
            if ( fPixel1 == null || fPixel2 == null )
            {
                DosePlaneDirectBitmap.Bits[x + y * xLength] = ( alpha << 24 ) | 0x8B;
                continue;
            }

            // HERE IS THE PROBLEM SPOT, SOMEHOW CAUSING fPixel1 TO BECOME NULL IN THE FUNCTION 
            double doseValue = NormalizationPoint.CalculatedDose( fPixel1, fPixel2, uncompensatedBeams, new Vector3D( xLocation, yLocation, PlaneZ ) ) / NormalizationPoint.LastEstimatedDose;
            output[x, y] = doseValue;
        }
        else
        {
            //DosePlaneBitmap.SetPixel( x, y, Color.FromArgb(alpha, 0, 0, 0x8B)); // dark blue
            DosePlaneDirectBitmap.Bits[x + y * xLength] = ( alpha << 24 ) | 0x8B;
        }
    }
}
);

再次,只需用

替换Parallel.For
for ( int y = 0; y < yLength; y++ )

不会导致静态CalculateDose函数内的空指针异常(不会以任何方式重载)。有什么想法吗?

1 个答案:

答案 0 :(得分:3)

此行将修改fPixel1

if (( fPixel1 = fluences[0].GetIntersectingFluencePixel( pixelLocation ) ) != null
        && ( fPixel2 = fluences[1].GetIntersectingFluencePixel( pixelLocation ) ) != null )

由于fPixel1似乎是在for循环之外声明的,因此所有各种​​线程都可以访问它,并且其他一些线程可能已将其设置为null。

我的建议是在for循环中声明fPixel1。作为一般规则,变量应该尽可能紧凑,所以我实际上将它放在内部循环中:

Parallel.For(0, yLength, y =>
{
    for ( int x = 0; x < xLength; x++ )
    {
        double xLocation = ImageData.Origin.X + ( 0.5 + x ) * ImageData.XRes; // offset by half pixel to get center of pixel
        double yLocation = ImageData.Origin.Y + ( 0.5 + y ) * ImageData.YRes;
        Vector3D pixelLocation = new Vector3D( xLocation, yLocation, PlaneZ );
        FluencePixel fPixel1 = fluences[0].GetIntersectingFluencePixel( pixelLocation );
        FluencePixel fPixel2 = fluences[1].GetIntersectingFluencePixel( pixelLocation );

        if ( fPixel1 != null && fPixel2 != null)
        {
           //Etc.....

我也摆脱了“如果条件内部的分配”,因为这显然是一个混乱的构造。