WP7中的加速度计问题

时间:2010-11-05 18:26:17

标签: c# windows-phone-7 accelerometer

我试图使用摇动动作来清除墨水预告器的内容,但是震动只会让我的应用程序崩溃。这是代码:

    public class ShakeDetect
{
    private Accelerometer _accelerometer = null;
    object SyncRoot = new object();
    private int _minimumShakes;
    ShakeRecord[] _shakeRecordList;
    private int _shakeRecordIndex = 0;
    private const double MinimumAccelerationMagnitude = 1.2;
    private const double MinimumAccelerationMagnitudeSquared = MinimumAccelerationMagnitude * MinimumAccelerationMagnitude;
    private static readonly TimeSpan MinimumShakeTime = TimeSpan.FromMilliseconds(500);

    public event EventHandler<EventArgs> ShakeEvent = null;


    protected void OnShakeEvent()
    {
        if (ShakeEvent != null)
        {
            ShakeEvent(this, new EventArgs());
        }
    }



    [Flags]
    public enum Direction
    {
        None = 0,
        North = 1,
        South = 2,
        East = 8,
        West = 4,
        NorthWest = North | West,
        SouthWest = South | West,
        SouthEast = South | East,
        NorthEast = North | East
    } ;

    public struct ShakeRecord
    {
        public Direction ShakeDirection;
        public DateTime EventTime;
    }


    public ShakeDetect()
        : this(2)
    {

    }
    public ShakeDetect(int minShakes)
    {
        _minimumShakes = minShakes;
        _shakeRecordList = new ShakeRecord[minShakes];
    }

    public void Start()
    {
        lock (SyncRoot)
        {
            if (_accelerometer == null)
            {
                _accelerometer = new Accelerometer();
                _accelerometer.ReadingChanged += new EventHandler<AccelerometerReadingEventArgs>(_accelerometer_ReadingChanged);
                _accelerometer.Start();
            }
        }
    }

    public void Stop()
    {
        lock (SyncRoot)
        {
            if (_accelerometer != null)
            {
                _accelerometer.Stop();
                _accelerometer.ReadingChanged -= _accelerometer_ReadingChanged;
                _accelerometer = null;
            }
        }
    }

    Direction DegreesToDirection(double direction)
    {
        if ((direction >= 337.5) || (direction <= 22.5))
            return Direction.North;
        if ((direction <= 67.5))
            return Direction.NorthEast;
        if (direction <= 112.5)
            return Direction.East;
        if (direction <= 157.5)
            return Direction.SouthEast;
        if (direction <= 202.5)
            return Direction.South;
        if (direction <= 247.5)
            return Direction.SouthWest;
        if (direction <= 292.5)
            return Direction.West;
        return Direction.NorthWest;
    }

    void CheckForShakes()
    {
        int startIndex = (_shakeRecordIndex - 1);
        if (startIndex < 0) startIndex = _minimumShakes - 1;
        int endIndex = _shakeRecordIndex;

        if ((_shakeRecordList[endIndex].EventTime.Subtract(_shakeRecordList[startIndex].EventTime)) <= MinimumShakeTime)
        {
            OnShakeEvent();
        }
    }
    void _accelerometer_ReadingChanged(object sender, AccelerometerReadingEventArgs e)
    {

        if ((e.X * e.X + e.Y * e.Y) > MinimumAccelerationMagnitudeSquared)
        {

            double degrees = 180.0 * Math.Atan2(e.Y, e.X) / Math.PI;
            Direction direction = DegreesToDirection(degrees);


            if ((direction & _shakeRecordList[_shakeRecordIndex].ShakeDirection) != Direction.None)
                return;
            ShakeRecord record = new ShakeRecord();
            record.EventTime = DateTime.Now;
            record.ShakeDirection = direction;
            _shakeRecordIndex = (_shakeRecordIndex + 1) % _minimumShakes;
            _shakeRecordList[_shakeRecordIndex] = record;

            CheckForShakes();

        }
    }

}

然后在我的应用中使用:

        private ShakeDetect _shakeDecetor;

    // Constructor
    public MainPage()
    {
        InitializeComponent();
        _shakeDecetor = new ShakeDetect();
        _shakeDecetor.ShakeEvent += new EventHandler<EventArgs>(_shakeDetect_ShakeEvent);
        _shakeDecetor.Start();

最后检测到震动时:

void _shakeDetect_ShakeEvent(object sender, EventArgs e)
    {
        CanvasIP.Strokes.Clear();
        CanvasIP.Background = new SolidColorBrush(Colors.Black);
    }

我猜这个问题出现在我的ShakeDetect类或ShakeEvent中。

好的,所以从汉斯的建议我的代码应该是:

void _shakeDetect_ShakeEvent(object sender, EventArgs e)
    {
        this.Dispatcher.BeginInvoke(() =>
            {
                CanvasIP.Strokes.Clear();
                CanvasIP.Background = new SolidColorBrush(Colors.Black);
            });
    }

现在这是正确的吗?

1 个答案:

答案 0 :(得分:4)

在另一个线程上引发了ReadingChanged事件。您可以直接触摸UI组件,您必须将回调编组回主线程。使用Dispatcher.BeginInvoke(),在MSDN library article中有详细描述。