【发布时间】:2016-05-16 15:32:38
【问题描述】:
我本来想发个问题,非多线程同步代码怎么可能出现以下情况:
但我在写问题时想出了答案:在计算时,等式中的被除数似乎为零,但之后会迅速改变值(注意:这个错误是罕见的,复制非确定性地,通常当我在 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){...}
}
【问题讨论】:
-
您知道所有 UI 都是单线程的,并且属性更改事件没有在多个线程上运行吗?
-
没有多线程
-
我们能看到
Model的代码吗? -
我会在几秒钟内发布相关的电话,但没有免费的工作人员、任务、线程或等待对象,如果那是你所追求的。只是库调用。
-
虽然不是不可能,但很可能发生的数学不一致地试图弄清楚括号在说什么。按照您显示的值
45829.5 / ((45829.5 + 45829.5) / 2) * 100是您的等式。这等于45829.5 / (45829.5) * 100或1 * 100。尝试将您的算法更改为(45829.5 / ((45829.5 + 45829.5) / 2)) * 100可能完全没有区别,但值得一试