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

Parallel.For causing static function non-null parameter to become null

我有一个没有问题的双 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 在 CalculateEstimatedDose 的正文中以某种方式变为空(未在任何地方设置它)。奇怪的是,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 函数(未以任何方式重载)内的空指针异常。有什么想法吗?

这一行将修改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.....

我也摆脱了 "assignment inside if condition" 因为这显然是一个令人困惑的结构。