翼度科技»论坛 编程开发 .net 查看内容

MAUI 已知问题 PathFigureCollectionConverter 非线程安全

7

主题

7

帖子

21

积分

新手上路

Rank: 1

积分
21
在 MAUI 里,可以使用 PathFigureCollectionConverter 将 Path 字符串转换为 PathFigureCollection 对象,从而实现从 Path 字符串转换为路径几何。然而这个 PathFigureCollectionConverter 转换器非线程安全,即使创建多个实例对象,依然由于内部的静态字段导致非线程安全,本文将记录此问题的原理
当前,此 PathFigureCollectionConverter 非线程安全问题,没有规避方法
我将此问题报告给官方,请看 https://github.com/dotnet/maui/issues/11321
然后官方说,你也是 Member 了,是一个成熟的开发者了,自己发现的问题就要自己修。于是我乖乖修了这个问题,请看 https://github.com/dotnet/maui/pull/11497 修了之后发现性能居然还提升了一点
复现步骤:
只需要让 PathFigureCollectionConverter 进入多线程转换 Path 字符串即可,转换过程,将随机抛出异常
最简代码如下
  1.         var pathFigureCollectionConverter = new PathFigureCollectionConverter();
  2.         var pathString1 =
  3.             "M320 96a64 64 0 0 0-64 64V896a64 64 0 0 0 64 64h384a64 64 0 0 0 64-64V160a64 64 0 0 0-64-64H320z m384 64V896H320V160h384zM128 256v576h64V256H128zM832 256v576h64V256h-64z";
  4.         var pathString2 =
  5.             "M230.08 738.56l58.816 58.88L574.336 512l-285.44-285.44-58.88 58.88L456.704 512l-226.56 226.56z m487.04 29.44V256h-83.2v512h83.2z";
  6.         _ = pathFigureCollectionConverter.ConvertFrom(pathString1);
  7.         _ = pathFigureCollectionConverter.ConvertFrom(pathString2);
  8.         for (int i = 0; i < 100; i++)
  9.         {
  10.             Task.Run(() =>
  11.             {
  12.                 var pathFigureCollection = pathFigureCollectionConverter.ConvertFrom(pathString1);
  13.             });
  14.         }
  15.         for (int i = 0; i < 100; i++)
  16.         {
  17.             Task.Run(() =>
  18.             {
  19.                 var pathFigureCollection = pathFigureCollectionConverter.ConvertFrom(pathString2);
  20.             });
  21.         }
复制代码
包含此代码的项目放在 GitHub 上,请看 https://github.com/lindexi/lindexi_gd/tree/abc3042ddbfc3bd46563119fc88df0463b155c8b/TestPathFigureCollectionConverter
导致 PathFigureCollectionConverter 非线程安全的核心原因是采用静态字段记录状态,以下是 PathFigureCollectionConverter 的部分源代码,代码有删减
  1.         static bool _figureStarted;
  2.         static string _pathString;
  3.         static int _pathLength;
  4.         static int _curIndex;
  5.         static Point _lastStart;
  6.         static Point _lastPoint;
  7.         static Point _secondLastPoint;
  8.         static char _token;
  9.         static void ParseToPathFigureCollection(PathFigureCollection pathFigureCollection, string pathString, int startIndex)
  10.         {
  11.             PathFigure pathFigure = null;
  12.             _pathString = pathString;
  13.             _pathLength = pathString.Length;
  14.             _curIndex = startIndex;
  15.             // 忽略其他代码
  16.         }
复制代码
完全的代码请看 https://github.com/dotnet/maui/blob/a541df0816d1867f494186a0bdc214d431e000cd/src/Controls/src/Core/Shapes/PathFigureCollectionConverter.cs
从上面代码可以看到,用到了静态字段。这是非多线程安全的,多个线程将会随机更改污染静态字段,从而让转换逻辑无法成功执行

来源:https://www.cnblogs.com/lindexi/archive/2023/01/09/17038313.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具