[英]Why doesn't the lock work in this scenario?
public class BodyRefiner
{
private KinectBody[] bodies = new KinectBody[6];
private KinectBody[] copiedBodies = new KinectBody[6];
public static readonly object locker = new object();
BodyDirectionCalculator directionCalculator;
JointOrientationCalculator orientationCalculator;
private BodyManipulator manipulator;
public BodyRefiner()
{
directionCalculator = new BodyDirectionCalculator();
orientationCalculator = new JointOrientationCalculator();
}
public void AttachBodyManipulator(BodyManipulator manipulatorToAttach)
{
this.manipulator = manipulatorToAttach;
}
public void DettachBodyManipulator()
{
this.manipulator = null;
}
public void UpdateBodies(Body[] acquiredBodies)
{
for(int i = 0; i < acquiredBodies.Length; i++)
{
this.bodies[i] = new KinectBody(acquiredBodies[i]);
directionCalculator.CalculateDirections(ref this.bodies[i]);
orientationCalculator.CalculateJointOrientations(ref this.bodies[i]);
}
CopyBodies();
}
public KinectBody[] GetBodies()
{
lock(locker)
{
foreach(KinectBody b in copiedBodies)
{
Debug.Log(b.isTracked);
}
return copiedBodies;
}
}
private void CopyBodies()
{
lock (locker)
{
copiedBodies = bodies;
if (manipulator != null)
{
copiedBodies = manipulator.GetManipulatedBodies(copiedBodies);
}
foreach (KinectBody b in copiedBodies)
{
Debug.Log(b.isTracked);
}
}
}
}
public class BodySource : Singleton<BodySource>
{
private Body[] bodies;
private KinectSensor sensor;
private BodyFrameReader reader;
public BodyRefiner contributor;
private Thread worker;
void Awake()
{
base.Awake();
sensor = KinectSensor.GetDefault();
if (!sensor.IsOpen)
{
sensor.Open();
}
BodyFrameSource source = sensor.BodyFrameSource;
reader = source.OpenReader();
bodies = new Body[source.BodyCount];
contributor = new BodyRefiner();
worker = new Thread(AcquireBodyFrame);
worker.Start();
}
void AcquireBodyFrame()
{
if (reader != null)
{
using (var frame = reader.AcquireLatestFrame())
{
if (frame != null)
{
frame.GetAndRefreshBodyData(bodies);
frame.Dispose();
contributor.UpdateBodies(bodies);
}
}
}
Thread.Sleep(1000 / 30);
AcquireBodyFrame();
}
void OnApplicationQuit()
{
worker.Abort();
worker = null;
}
}
public class CustomTrackingTryFullChar : MonoBehaviour {
private Transform[] bones;
private Quaternion[] initialRotations;
public Animator animator;
private Quaternion initRot;
private Alpaca.Kinect.KinectGameComponent comp;
public TrackingMask mask;
public float smoothFactor;
KinectTest.KinectBody b;
Transform boneTransform;
Quaternion jointRotation;
KinectTest.KinectBody[] trackedBodies;
// Use this for initialization
void Start () {
bones = new Transform[27];
MapBones();
initialRotations = new Quaternion[bones.Length];
GetInitialRotations();
comp = GetComponent<Alpaca.Kinect.KinectGameComponent>();
KinectTest.BodyManipulator manipulator = new KinectTest.BodyManipulator();
manipulator.wantedAmountOfTrackedBodies = 0;
KinectTest.BodySource.Instance.contributor.AttachBodyManipulator(manipulator);
}
private void MapBones()
{
for (int boneIndex = 0; boneIndex < bones.Length; boneIndex++)
{
if (!BoneMaps.boneIndex2MecanimMap.ContainsKey(boneIndex))
continue;
bones[boneIndex] = this.animator.GetBoneTransform(BoneMaps.boneIndex2MecanimMap[boneIndex]);
}
}
private void GetInitialRotations()
{
Quaternion temp = this.transform.rotation;
this.transform.rotation = Quaternion.identity;
for (int i = 0; i < bones.Length; i++)
{
if (bones[i] != null)
{
initialRotations[i] = bones[i].rotation;
}
}
this.transform.rotation = temp;
}
// Update is called once per frame
void Update () {
trackedBodies = KinectTest.BodySource.Instance.contributor.GetBodies();
foreach (KinectTest.KinectBody bd in trackedBodies)
{
if (bd.isTracked)
{
b = bd;
TransformBones();
}
}
}
bool IsJointTracked(KinectTest.KinectJoint joint)
{
return joint.trackingState == TrackingState.Tracked;
}
bool ShallJointBeTracked(JointType type)
{
return mask.TrackJoint(type);
}
void TransformBones()
{
for (int boneIndex = 0; boneIndex < bones.Length; boneIndex++)
{
if (!bones[boneIndex])
{
continue;
}
if (BoneMaps.boneIndex2JointMap.ContainsKey(boneIndex))
{
JointType joint = BoneMaps.boneIndex2JointMap[boneIndex];
TransformBone(joint, boneIndex, null, b.joints);
}
}
}
private void TransformBone(JointType joint, int boneIndex, Dictionary<JointType, Quaternion> orientations, Dictionary<JointType, KinectTest.KinectJoint> joints)
{
boneTransform = bones[boneIndex];
if (boneTransform == null)
{
return;
}
int iJoint = (int)joint;
if (iJoint < 0 || !this.IsJointTracked(b.joints[joint]) || !ShallJointBeTracked(joint))
{
return;
}
// Get Kinect joint orientation
jointRotation = Quaternion.identity;
if (b.isTracked)
{
jointRotation = b.joints[joint].rotation;
}
if (jointRotation == Quaternion.identity)
return;
Kinect2AvatarRot(jointRotation, boneIndex);
if (smoothFactor != 0f)
{
boneTransform.rotation = Quaternion.Slerp(boneTransform.rotation, newRotation, smoothFactor * Time.deltaTime);
}
else
{
boneTransform.rotation = newRotation;
}
}
Quaternion newRotation;
Vector3 totalRotation;
private Quaternion Kinect2AvatarRot(Quaternion jointRotation, int boneIndex)
{
newRotation = jointRotation * initialRotations[boneIndex];
totalRotation = newRotation.eulerAngles + this.transform.rotation.eulerAngles;
newRotation = Quaternion.Euler(totalRotation);
return newRotation;
}
}
如您所见,BodySource在另一个线程中更新,并且也更新了BodyRefiner。 Body Refiner包含一个GetBodies()方法,该方法从主循环中调用。 CopyBodies()和GetBodies()中的调试日志不会记录相同的结果。 当在这两种方法中使用lock语句时,如何发生这种情况?
CopyBodies()在记录抄录成员之前对其进行更改,因此,如果在CopyBodies()之前调用GetBodies(),您将获得不同的日志,因为GetBodies()将记录旧成员,而CopyBodies()将记录新成员。
我只是对bodys数组进行了深拷贝,因此每次编辑它时,我的copyedBodies数组也都会更改。 由于我的UpdateBodies()方法没有锁定,因此遇到了这些同步错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.