繁体   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;
    }


}

如您所见,BodySource在另一个线程中更新,并且也更新了BodyRefiner。 Body Refiner包含一个GetBodies()方法,该方法从主循环中调用。 CopyBodies()和GetBodies()中的调试日志不会记录相同的结果。 当在这两种方法中使用lock语句时,如何发生这种情况?

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

我只是对bodys数组进行了深拷贝,因此每次编辑它时,我的copyedBodies数组也都会更改。 由于我的UpdateBodies()方法没有锁定,因此遇到了这些同步错误。

暂无
暂无

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

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