由于财产变更事件缓慢导致不可能的结果

时间:2016-05-16 15:32:39

标签: c# c#-6.0

我原本想发一个问题,多线程,同步代码如何可能出现以下情况:

Debugging screen

但是我在写这个问题时想出了答案:似乎在计算时方程中的红利为零,但在此之后迅速改变了值(注意:这个错误是罕见的,重复非确切地说,通常当我在DataGrid上向上/向下箭头时。)

相关代码如下所示:

        public double? LeftPolyArea => Model.GetArea(LeftPolyName);
        public double? RightPolyArea => Model.GetArea(RightPolyName);
        public double? RightPolyNonOverlappingArea =>Model.GetNonOverlappingArea(RightPolyName, LeftPolyName);
        public double? ResemblenceIndex
        {
            get
            {
                if (!(LeftPolyOverlappingArea.HasValue && LeftPolyArea.HasValue && RightPolyArea.HasValue)) return null;
                var index = LeftPolyOverlappingArea.Value / ((LeftPolyArea.Value + RightPolyArea.Value) / 2) * 100;
                return Math.Round(index, 1);
            }
        }

并立即触发NotifyPropertyChanged事件:

public void Refresh()
        {
            OnPropertyChanged(nameof(LeftPolyArea));
            OnPropertyChanged(nameof(RightPolyArea));
            OnPropertyChanged(nameof(ResemblenceIndex));
        }

我看到,如果我坚持通常的Notify属性,它就不会发生,但我真的没有看到,为什么它不能正常工作。我理解如果这两个被触发的事件改变了一些现有的变量,而不是快速访问会产生'旧'值,但那些是获取属性,所以控制流不应该在计算完成之前进行,对吧?这有什么不对?

[编辑]我正在添加模型代码: [EDIT2]几乎完整的型号代码:

public class SpatialMapsModel : ISpatialMapsModel
{
    public int RoundDigits { get; set; } = 1;

    public IOService InputOutputService { get; }

    public SpatialMapsModel(IOService ioService)
    {
        InputOutputService = ioService;
    }

    public bool IsPolygonValid(IList<C2DPoint> polygon)
    {
        return polygon?.Count > 2
    }

    public enum IntersectionType
    {
        Overlapping,
        NonOverlapping
    }

    public List<C2DHoledPolygon> GetIntersectingPolygons(IList<C2DPoint> pointsA, IList<C2DPoint> pointsB, IntersectionType whichPolygons)
    {
        var leftPoly = new C2DPolygon(pointsA.ToList(), true);
        var rightPoly = new C2DPolygon(pointsB.ToList(), true);
        rightPoly.RandomPerturb();
        var someGrid = new CGrid();
        var smallPolygons = new List<C2DHoledPolygon>();
        switch (whichPolygons)
        {
            case IntersectionType.Overlapping:
                leftPoly.GetOverlaps(rightPoly, smallPolygons, someGrid);
                break;
            case IntersectionType.NonOverlapping:
                leftPoly.GetNonOverlaps(rightPoly, smallPolygons, someGrid);
                break;
            default:
                throw new ArgumentException(nameof(whichPolygons));
        }
        return smallPolygons;
    }

    public double? GetOverlappingArea(IList<C2DPoint> pointsA, IList<C2DPoint> pointsB)
    {
        var polygons = GetIntersectingPolygons(pointsA, pointsB, IntersectionType.Overlapping);
        var area = polygons.Sum(p => p.GetArea());
        return Math.Round(area, RoundDigits);
    }

    public double? GetNonOverlappingArea(IList<C2DPoint> pointsA, IList<C2DPoint> pointsB)
    {
        var polygons = GetIntersectingPolygons(pointsA, pointsB, IntersectionType.NonOverlapping);
        var area = polygons.Sum(p => p.GetArea());
        return Math.Round(area, RoundDigits);
    }

    private Tuple<double, double, double, double> MinMax(IList<C2DPoint> input)
    {
        var minX = double.MaxValue;
        var minY = double.MaxValue;
        var maxX = double.MinValue;
        var maxY = double.MinValue;
        foreach (var t in input)
        {
            if (t.X < minX)
                minX = t.x;
            if (t.y < minY)
                minY = t.y;
            if (t.X > maxX)
                maxX = t.x;
            if (t.y > maxY)
                maxY = t.y;
        }
        return new Tuple<double, double, double, double>(minX, minY, maxX, maxY);
    }
    public void SnapToOriginInPlace(IList<C2DPoint> input)
    {
        var minXy = MinMax(input);
        for (var i = 0; i < input.Count; ++i)
        {
            input[i] = new C2DPoint(input[i].X - minXy.Item1, input[i].Y - minXy.Item2);
        }
        var poly = new C2DPolygon(input.ToList(), true);
        poly.RandomPerturb();
        var pointsCopy = new C2DPointSet();
        poly.GetPointsCopy(pointsCopy);
        for (var i = 0; i < pointsCopy.Count; ++i)
        {
            input[i] = pointsCopy[i];
        }
    }
    public KeyValuePair<string, List<C2DPoint>> GetPolygonFromFile(string fileName){...}

    public void WritePolygonToFile(IList<C2DPoint> poly, string fileName){...}

    public double? GetArea(IList<C2DPoint> points)
    {
        if (IsPolygonValid(points))
        {
            var poly = new C2DPolygon(points.ToList(), true);
            var area = poly.GetArea();
            return Math.Round(area, RoundDigits);
        }
        return null;
    }

    public double? GetPerimeter(IList<C2DPoint> points){...}
}

1 个答案:

答案 0 :(得分:0)

问题来自我使用的库GeoLib,当一个点的X或Y值与其他X或Y完全等于重叠时。随机扰动应该防止这种情况,但它偶尔(随机......)不这样做,尤其是在缩放和变换多边形时。 Hovewer仍然没有回答,为什么在计算过程中价值会发生变化。