C# 错误:调用线程无法访问此对象,因为其他线程拥有它。故事板模拟

C# 错误:调用线程无法访问此对象,因为其他线程拥有它。故事板模拟,c#,wpf,C#,Wpf,对于我的学校项目,我正在尝试投射物模拟,但决定使用故事板(不确定这是否是正确的想法),因此到目前为止我的代码。正如您从标题中看到的,我在尝试执行时出现了错误 ellipseStoryboard.Begin(这个); 但是我看不出我做错了什么。谢谢你的帮助 我的代码: void onTimedEvent(Object sender, ElapsedEventArgs t, particle newProjectile, double TimeInterval, int i, Path myPath

对于我的学校项目,我正在尝试投射物模拟,但决定使用故事板(不确定这是否是正确的想法),因此到目前为止我的代码。正如您从标题中看到的,我在尝试执行时出现了错误 ellipseStoryboard.Begin(这个); 但是我看不出我做错了什么。谢谢你的帮助

我的代码:

void onTimedEvent(Object sender, ElapsedEventArgs t, particle newProjectile, double TimeInterval, int i, Path myPath, Canvas AnimationCanvas)
{
    this.Dispatcher.Invoke((Action)(() =>
    {
        AnimationCanvas.Children.Clear();
    }));

    PointAnimation myPointAnimation = new PointAnimation();
    myPointAnimation.Duration = TimeSpan.FromSeconds(TimeInterval);
    myPointAnimation.RepeatBehavior = new RepeatBehavior(1);
    myPointAnimation.From = new System.Windows.Point(newProjectile.HDisplacement[i], newProjectile.VDisplacement[i]);
    myPointAnimation.To = new System.Windows.Point(newProjectile.HDisplacement[i + 1], newProjectile.VDisplacement[i + 1]);
    Storyboard.SetTargetName(myPointAnimation, "MyAnimatedEllipseGeometry");
    Storyboard.SetTargetProperty(myPointAnimation, new PropertyPath(EllipseGeometry.CenterProperty));
    Storyboard ellipseStoryboard = new Storyboard();
    ellipseStoryboard.Children.Add(myPointAnimation);
    this.Dispatcher.Invoke((Action)(() =>
    {
        myPath.Loaded += delegate(object sender1, RoutedEventArgs e)
        {
            ellipseStoryboard.Begin(this);
        };
    }));
    this.Dispatcher.Invoke((Action)(() =>
    {
        AnimationCanvas.Children.Add(myPath);
    }));

}

编辑:我已经计算了实际的位移点,并将它们放在一个数组中

您可能不需要更多:

myPath.Loaded +=
    (o, e) =>
    {
        var myPointAnimation = new PointAnimation
        {
            Duration = TimeSpan.FromSeconds(TimeInterval),
            From = new Point(...),
            To = new Point(...)
        };
        MyAnimatedEllipseGeometry.BeginAnimation(
            EllipseGeometry.CenterProperty, myPointAnimation);
    };

虽然投射物的x和y坐标的独立动画(例如,通过故事板中的两个动画)以及y坐标的二次缓和函数将允许模拟重力,但您可能会更好地使用具有时间相关运动学的真实物理模拟

private Point position; // in pixels
private Vector velocity; // in pixels per second
private Vector acceleration; // in pixels per square second
private DateTime time;

public MainWindow()
{
    InitializeComponent();
    Loaded += OnLoaded;
}

private void OnLoaded(object sender, RoutedEventArgs e)
{
    position = new Point(100, 100);
    velocity = new Vector(50, -50); // y direction is downwards
    acceleration = new Vector(0, 20); // y direction is downwards
    time = DateTime.Now;
    CompositionTarget.Rendering += OnRendering;
}

private void OnRendering(object sender, EventArgs e)
{
    var t = DateTime.Now;
    var dt = (t - time).TotalSeconds;
    time = t;

    position += velocity * dt;
    velocity += acceleration * dt;

    projectileGeometry.Center = position;

    if (position.Y > ActualHeight)
    {
        CompositionTarget.Rendering -= OnRendering;
    }
}
上述内容的简单版本可能如下所示:

<Path Fill="Black">
    <Path.Data>
        <EllipseGeometry x:Name="projectileGeometry" RadiusX="5" RadiusY="5"/>
    </Path.Data>
</Path>

您可能不需要更多:

myPath.Loaded +=
    (o, e) =>
    {
        var myPointAnimation = new PointAnimation
        {
            Duration = TimeSpan.FromSeconds(TimeInterval),
            From = new Point(...),
            To = new Point(...)
        };
        MyAnimatedEllipseGeometry.BeginAnimation(
            EllipseGeometry.CenterProperty, myPointAnimation);
    };

虽然投射物的x和y坐标的独立动画(例如,通过故事板中的两个动画)以及y坐标的二次缓和函数将允许模拟重力,但您可能会更好地使用具有时间相关运动学的真实物理模拟

private Point position; // in pixels
private Vector velocity; // in pixels per second
private Vector acceleration; // in pixels per square second
private DateTime time;

public MainWindow()
{
    InitializeComponent();
    Loaded += OnLoaded;
}

private void OnLoaded(object sender, RoutedEventArgs e)
{
    position = new Point(100, 100);
    velocity = new Vector(50, -50); // y direction is downwards
    acceleration = new Vector(0, 20); // y direction is downwards
    time = DateTime.Now;
    CompositionTarget.Rendering += OnRendering;
}

private void OnRendering(object sender, EventArgs e)
{
    var t = DateTime.Now;
    var dt = (t - time).TotalSeconds;
    time = t;

    position += velocity * dt;
    velocity += acceleration * dt;

    projectileGeometry.Center = position;

    if (position.Y > ActualHeight)
    {
        CompositionTarget.Rendering -= OnRendering;
    }
}
上述内容的简单版本可能如下所示:

<Path Fill="Black">
    <Path.Data>
        <EllipseGeometry x:Name="projectileGeometry" RadiusX="5" RadiusY="5"/>
    </Path.Data>
</Path>

看起来您正在尝试从计时器启动动画。如果您收到一个线程错误,您可能在错误的线程上。不要使用
Dispatcher.Invoke
进行编组,只需使用
DispatcherTimer
即可确保您的回调位于UI线程上

而不是:

var timer = new System.Timers.Timer(1000);
timer.Elapsed += tmrHandler;
timer.Enabled = true;
使用


看起来您正在尝试从计时器启动动画。如果您收到一个线程错误,您可能在错误的线程上。不要使用
Dispatcher.Invoke
进行编组,只需使用
DispatcherTimer
即可确保您的回调位于UI线程上

而不是:

var timer = new System.Timers.Timer(1000);
timer.Elapsed += tmrHandler;
timer.Enabled = true;
使用


其实我有点困惑。。。我想做的是让多个点作为newPointAnimations相互绘制。我现在把它拆了,这样它就不用定时器了。但我似乎无法让动画彼此链接如果我使用你的代码它会取代我的大部分代码吗?为什么基于帧的动画比使用故事板更好?这是否意味着你有一组预先计算的点用作后续动画的目标?如果是这样的话,你可能会在你的问题中提到这一点。我理解你的问题,你正试图建立一个弹丸运动学的模拟。基于帧的动画将是一个理想的解决方案,因为它为您提供了回调方法(CompositionTarget.Rendering事件),允许您根据当前时间戳计算下一个模拟步骤。我们会尽可能多地打电话,但不会超过必要的次数。对不起,我的不好,但我有预先计算好的分数。但是你认为我使用基于帧的动画会更好吗?实际上我有点困惑。。。我想做的是让多个点作为newPointAnimations相互绘制。我现在把它拆了,这样它就不用定时器了。但我似乎无法让动画彼此链接如果我使用你的代码它会取代我的大部分代码吗?为什么基于帧的动画比使用故事板更好?这是否意味着你有一组预先计算的点用作后续动画的目标?如果是这样的话,你可能会在你的问题中提到这一点。我理解你的问题,你正试图建立一个弹丸运动学的模拟。基于帧的动画将是一个理想的解决方案,因为它为您提供了回调方法(CompositionTarget.Rendering事件),允许您根据当前时间戳计算下一个模拟步骤。我们会尽可能多地打电话,但不会超过必要的次数。对不起,我的不好,但我有预先计算好的分数。但是你认为我使用基于帧的动画会更好吗?