Calling Thread must be STA

2019-03-05 09:23发布

I am trying to simulate a projectile and trying to create the labels in the timed event only once, because it has an object in the parameter which i need to be in the timed event. But i get this threading error when i run it. Help please!

My Code is :

    void onTimedEvent(Object source, ElapsedEventArgs e)
    {
        particle newProjectile;
        newProjectile = new particle();

        bool LabelExist = false;
        if (LabelExist == false)
        {
            CreateLabels(newProjectile);
        }
    }

        aTimer = new System.Timers.Timer(200);
        aTimer.Elapsed += onTimedEvent;
        aTimer.Enabled = true;

    void CreateLabels(particle newProjectile)
    {
        DockPanel panelcontrol_displacement, panelcontrol_CurrentVel, panelcontrol_VerticalVel, panelcontrol_HorizontalVel, panelcontrol_Time;
        Label lbl_TimeUnits, lbl_TimeOutput, lbl_Time, lbl_DisplacementOutput, lbl_DisplacementUnits, lbl_Displacement, lbl_CurrentVel, lbl_CurrentVelOutput, lbl_HorizontalVelocityOutputs, lbl_HorizontalVelocityUnits, lbl_VerticalVelocity, lbl_HorizontalVelocity, lbl_CurrentVelUnits, lbl_VerticalVelocityOutput, lbl_VerticalVelocityUnits;
        lbl_Time = new Label();
        lbl_Time.Content = "Time";
        lbl_Time.Height = 30;
        lbl_Time.Width = 110;
        lbl_TimeOutput = new Label();
        lbl_TimeOutput.Content = "20";
        lbl_TimeOutput.Height = 30;
        lbl_TimeOutput.Width = 100;
        lbl_TimeOutput.HorizontalContentAlignment = HorizontalAlignment.Right;
        lbl_TimeUnits = new Label();
        lbl_TimeUnits.Content = "s";
        lbl_CurrentVel = new Label();
        lbl_CurrentVel.Content = "Current Velocity";
        lbl_CurrentVel.Height = 30;
        lbl_CurrentVel.Width = 110;
        lbl_CurrentVelOutput = new Label();
        lbl_CurrentVelOutput.Content = "20";
        lbl_CurrentVelOutput.Height = 30;
        lbl_CurrentVelOutput.Width = 100;
        lbl_CurrentVelOutput.HorizontalContentAlignment = HorizontalAlignment.Right;
        lbl_CurrentVelUnits = new Label();
        lbl_CurrentVelUnits.Content = "m/s";
        lbl_VerticalVelocity = new Label();
        lbl_VerticalVelocity.Content = "Verticle Velocity";
        lbl_VerticalVelocity.Height = 30;
        lbl_VerticalVelocity.Width = 110;
        lbl_VerticalVelocityOutput = new Label();
        lbl_VerticalVelocityOutput.Content = "20";
        lbl_VerticalVelocityOutput.Height = 30;
        lbl_VerticalVelocityOutput.Width = 100;
        lbl_VerticalVelocityOutput.HorizontalContentAlignment = HorizontalAlignment.Right;
        lbl_VerticalVelocityUnits = new Label();
        lbl_VerticalVelocityUnits.Content = "m/s";
        lbl_HorizontalVelocity = new Label();
        lbl_HorizontalVelocity.Content = "Horizontal Velocity";
        lbl_HorizontalVelocity.Height = 30;
        lbl_HorizontalVelocity.Width = 110;
        lbl_HorizontalVelocityOutputs = new Label();
        lbl_HorizontalVelocityOutputs.Content = "20";
        lbl_HorizontalVelocityOutputs.Height = 30;
        lbl_HorizontalVelocityOutputs.Width = 100;
        lbl_HorizontalVelocityOutputs.HorizontalContentAlignment = HorizontalAlignment.Right;
        lbl_HorizontalVelocityUnits = new Label();
        lbl_HorizontalVelocityUnits.Content = "m/s";
        lbl_Displacement = new Label();
        lbl_Displacement.Content = "Displacement";
        lbl_Displacement.Height = 30;
        lbl_Displacement.Width = 110;
        lbl_DisplacementOutput = new Label();
        lbl_DisplacementOutput.Content = "20";
        lbl_DisplacementOutput.Height = 30;
        lbl_DisplacementOutput.Width = 100;
        lbl_DisplacementOutput.HorizontalContentAlignment = HorizontalAlignment.Right;
        lbl_DisplacementUnits = new Label();
        lbl_DisplacementUnits.Content = "m/s";
        panelcontrol_HorizontalVel = new DockPanel();
        panelcontrol_CurrentVel = new DockPanel();
        panelcontrol_VerticalVel = new DockPanel();
        panelcontrol_displacement = new DockPanel();
        panelcontrol_Time = new DockPanel();
        panelcontrol_CurrentVel.Children.Add(lbl_CurrentVel);
        panelcontrol_CurrentVel.Children.Add(lbl_CurrentVelOutput);
        panelcontrol_CurrentVel.Children.Add(lbl_CurrentVelUnits);
        panelcontrol_VerticalVel.Children.Add(lbl_VerticalVelocity);
        panelcontrol_VerticalVel.Children.Add(lbl_VerticalVelocityOutput);
        panelcontrol_VerticalVel.Children.Add(lbl_VerticalVelocityUnits);
        panelcontrol_HorizontalVel.Children.Add(lbl_HorizontalVelocity);
        panelcontrol_HorizontalVel.Children.Add(lbl_HorizontalVelocityOutputs);
        panelcontrol_HorizontalVel.Children.Add(lbl_HorizontalVelocityUnits);
        panelcontrol_displacement.Children.Add(lbl_Displacement);
        panelcontrol_displacement.Children.Add(lbl_DisplacementOutput);
        panelcontrol_displacement.Children.Add(lbl_DisplacementUnits);
        panelcontrol_Time.Children.Add(lbl_Time);
        panelcontrol_Time.Children.Add(lbl_TimeOutput);
        panelcontrol_Time.Children.Add(lbl_TimeUnits);
        StkPnl_Inputs.Children.Add(panelcontrol_Time);
        StkPnl_Inputs.Children.Add(panelcontrol_CurrentVel);
        StkPnl_Inputs.Children.Add(panelcontrol_VerticalVel);
        StkPnl_Inputs.Children.Add(panelcontrol_HorizontalVel);
        StkPnl_Inputs.Children.Add(panelcontrol_displacement);
        //databinding
        Binding(newProjectile, lbl_CurrentVelOutput, "CurrentVelocity");
    }

1条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-03-05 10:16

You get this error because it is not allowed to access UI from a background thread (the System.Timers.Timer.Elapsed handler is running on a background thread). This is because all the thread which handle UI in WPF should run in Single Threaded Apartment(STA) for synchronization purpose. And, the background workers do not run in STA.

Use a DispatcherTimer, instead of a System.Timers.Timer.

The remark section of the MSDN page outline the difference between the 2 timers.

If a System.Timers.Timer is used in a WPF application, it is worth noting that the System.Timers.Timer runs on a different thread then the user interface (UI) thread. In order to access objects on the user interface (UI) thread, it is necessary to post the operation onto the Dispatcher of the user interface (UI) thread using Invoke or BeginInvoke.

Reasons for using a DispatcherTimer opposed to a System.Timers.Timer are that the DispatcherTimer runs on the same thread as the Dispatcher and a DispatcherPriority can be set on the DispatcherTimer.

查看更多
登录 后发表回答