Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
TJson.JsonToObject<;T>;在多线程环境中抛出错误_Json_Multithreading_Delphi_Rest_Delphi Xe7 - Fatal编程技术网

TJson.JsonToObject<;T>;在多线程环境中抛出错误

TJson.JsonToObject<;T>;在多线程环境中抛出错误,json,multithreading,delphi,rest,delphi-xe7,Json,Multithreading,Delphi,Rest,Delphi Xe7,在多线程环境中使用TJson.JsonToObject时,会发生随机访问冲突。我花了很长时间寻找这个问题,我可以用下面的代码将它隔离开来 JSON类 type TParameter = class public FName : string; FDataType : string; FValue : string; end; 测试功能: procedure Test(); var myTasks: array of IT

在多线程环境中使用
TJson.JsonToObject
时,会发生随机访问冲突。我花了很长时间寻找这个问题,我可以用下面的代码将它隔离开来

JSON类

type
   TParameter = class
   public
      FName     : string;
      FDataType : string;
      FValue    : string;
   end;
测试功能:

procedure Test();
var
   myTasks: array of ITask;
   i : integer;
   max : integer;
begin

  max := 50;
  SetLength(myTasks, max);
  for i := 0 to max  -1  do begin
     myTasks[i] := TTask.Create(procedure ()
       var
          json : string;
          p : TParameter;
       begin
          json := '{"name":"NameOfParam","dataType":"TypeOfParam","value":"ValueOfParam"}';
          p := TJson.JsonToObject<TParameter>(json);
          p.Free;
       end);
     myTasks[i].Start;
  end;

  TTask.WaitForAll(myTasks);
  ShowMessage('all done!');
end;
程序测试();
变量
myTasks:ITask数组;
i:整数;
max:整数;
开始
最大值:=50;
设置长度(myTasks,最大值);
对于i:=0到最大值-1,开始
myTasks[i]:=TTask.Create(过程()
变量
json:string;
p:t参数;
开始
json:='{“名称”:“名称参数”,“数据类型”:“类型参数”,“值”:“值参数”}';
p:=TJson.JsonToObject(json);
p、 免费的;
(完),;
myTasks[i].启动;
结束;
TTask.WaitForAll(我的任务);
ShowMessage('all done!');
结束;

这只是一个基于更复杂源代码的代码片段。只要我在一个线程中使用这段代码,一切都可以正常工作。我想知道代码是否有问题。
REST.JsonReflect.pas
中的方法
tjsonmanmarshal.ObjectInstance
有一个严重的错误:

它在TRttiType实例上调用FreeAndNil。由于所有TRtti***实例都由TRttiContext管理,因此决不应执行此操作

在我删除FreeAndNil调用后,我无法再复制访问冲突

报告如下:


另外,我还认为这会影响您的代码。

哪个JSON库?它是线程安全的吗?为什么在调用
JsonToObject
时使用锁呢。如果代码使用锁运行良好,没有锁就失败了,那么这将表明
JsonToObject
不是线程安全的。我无法重现这一点。只需设置一个控制台应用程序并将您的
t参数
放在一个单独的单元中就可以了,没有例外
TTask
Proc
也表明反序列化发生在不同的线程中。@DavidHeffernan库来自embarcadero REST.jsi我认为问题出在RTTI中。它只是不线程安全。例如:我预计在这些线路上会有更多的问题,我相信会有线程安全问题。如果我序列化
tjsonumarshal.CreateObject
的执行,那么就没有错误。我认为你需要提交一份bug报告。您得到了一个漂亮的复制品。感谢您对此进行研究并报告+1感谢您的努力+1和一个问题:从错误报告中,不清楚是否只有通用方法调用受到影响(TJson.JsonToObject(json)-在XE7应用程序中,我看到零星的AVs,它使用TJson.JsonToObject(FSomeField,SomeJsonObject);