C# 为什么锁在这种情况下不起作用?
正如您所见,BodySource在另一个线程中得到更新,并同时更新BodyRefiner。主体细化器包含一个从主循环调用的getBodys方法。CopyBody和GetBody中的调试日志不会记录相同的结果。如果在这两种方法中都使用lock语句,怎么会出现这种情况?CopyBody在记录之前更改copiedBodies成员,因此如果在CopyBody之前调用GetBody,您将获得不同的日志,由于GetBody将记录旧成员,CopyBody将记录新成员。我刚刚制作了Body数组的深度副本,因此每次编辑它时,我的copiedBodies数组也会更改。因为我的UpdateBodies方法中没有锁,所以我遇到了这些同步错误 能否显示用于调用此方法的线程片段?能否共享locker对象的声明方式?您没有提供足够的代码来复制此问题。缺少的东西太多了。您正在访问其他地方使用的数据,而没有显示其他哪些数据正在接触相同的数据;我刚刚看过代码,CopyBodys方法完成后,CopyBodys IsTracket字段始终为false。而且复制体仅在复制体中修改,因此不能作为解决方案。C# 为什么锁在这种情况下不起作用?,c#,multithreading,locking,C#,Multithreading,Locking,正如您所见,BodySource在另一个线程中得到更新,并同时更新BodyRefiner。主体细化器包含一个从主循环调用的getBodys方法。CopyBody和GetBody中的调试日志不会记录相同的结果。如果在这两种方法中都使用lock语句,怎么会出现这种情况?CopyBody在记录之前更改copiedBodies成员,因此如果在CopyBody之前调用GetBody,您将获得不同的日志,由于GetBody将记录旧成员,CopyBody将记录新成员。我刚刚制作了Body数组的深度副本,因此每
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;
}
}