由于不同的线程拥有该对象,因此调用线程无法访问此对象。

8

我正在用c#/wpf创建一个简单的打砖块游戏,但在使用计时器时遇到了问题。我感觉这可能只是一个简单的修复,但以下是具体情况:每当t_Elapsed被触发时,它试图调用Update()方法,但此时就像“哎呀,我不在正确的线程中,无法执行该操作。” 我该如何从正确的线程中调用Game中的方法?(是的,我知道代码很丑陋,有着魔术数字,但我只是随便码出来的。而且,我零经验编程游戏)

public partial class Game : Grid
{
    public bool running;
    public Paddle p;
    public Ball b;
    Timer t;

    public Game()
    {
        Width = 500;
        Height = 400;
        t = new Timer(20);
        p = new Paddle();
        b = new Ball();
        for (int i = 15; i < 300; i += 15)
        {
            for (int j = 15; j < 455; j += 30)
            {
                Brick br = new Brick();
                br.Margin = new Thickness(j, i, j + 30, i + 15);
                Children.Add(br);
            }
        }
        Children.Add(p);
        Children.Add(b);
        p.Focus();
        t.AutoReset = true;
        t.Start();
        t.Elapsed += new ElapsedEventHandler(t_Elapsed);
    }

    void t_Elapsed(object sender, ElapsedEventArgs e)
    {
        if (running)
        {
            Update();
        }
    }

    void Update()
    {
        b.Update(); //Error here when Update is called from t_Elapsed event
    }

    void Begin()
    {
        running = true;
        b.Initiate();
    }
}

哦,我的天啊,我不在正确的线程中,所以我不能做到,先生。 <3 - Laserbeak43
3个回答

12

您应该使用DispatcherTimer对象,它将确保计时器事件发布到正确的线程。


API有些不同。例如,ElapsedTimeEvent现在被命名为TickEvent。但是迁移到新的API后,它可以很好地与UI线程一起工作!我喜欢.NET几乎每个场合都有快速解决方案;) - OneWorld

5
计时器已过去事件在线程池的线程上触发(http://www.albahari.com/threading/part3.aspx#_Timers),而不是在UI线程上触发。最好的方法是通过调用控件的调度程序来实现,如下所示:
yourControl.Dispatcher.BeginInvoke(
   System.Windows.Threading.DispatcherPriority.Normal
   , new System.Windows.Threading.DispatcherOperationCallback(delegate
   {
        // update your control here

        return null;
   }), null);

0

请问您能否从链接的问题中添加更多信息到这里。 - VMAtm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接