简体   繁体   English

为什么在这种情况下锁不起作用?

[英]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;
    }


}

As you see the BodySource gets updated in another thread and updates the BodyRefiner as well. 如您所见,BodySource在另一个线程中更新,并且也更新了BodyRefiner。 The Body Refiner contains a GetBodies() method which is called from the main loop. Body Refiner包含一个GetBodies()方法,该方法从主循环中调用。 The Debug Logs in CopyBodies() und GetBodies() dont log the same results. CopyBodies()和GetBodies()中的调试日志不会记录相同的结果。 How can something like this happen when the lock statement is used in both of the methods? 当在这两种方法中使用lock语句时,如何发生这种情况?

CopyBodies()在记录抄录成员之前对其进行更改,因此,如果在CopyBodies()之前调用GetBodies(),您将获得不同的日志,因为GetBodies()将记录旧成员,而CopyBodies()将记录新成员。

I just made a deep copy of the bodies array so every time i edited it, my copiedBodies array changed as well. 我只是对bodys数组进行了深拷贝,因此每次编辑它时,我的copyedBodies数组也都会更改。 Since i didnt have a lock in my UpdateBodies() method i ran into those synchronization errors. 由于我的UpdateBodies()方法没有锁定,因此遇到了这些同步错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM