Carl
Carl

Reputation: 618

Why do I get "Invalid cross-thread access" when using Dispatcher.BeginInvoke()?

I am looking into theading to improve my apps performance and am hitting abit of an issue. i am wanting to update the UI from another thread, from what i can gather i should be using Dispatcher.BeginInvoke for this however when i run the below code i get an error about not being able to access the other thread. any ideas?

The error is An Unhandled exception of type 'System.UnauthorizedAccessException' occurred in System.Windows.ni.dll

Additional information: Invalid cross-thread access."

public void StartPlaneThread()
    {
        var thread = new System.Threading.Thread(DoSomething);
        thread.Start();
    }

    private void DoSomething()
    {

        DispatcherTimer TimerTask;
        TimerTask = new DispatcherTimer();
        TimerTask.Tick += new EventHandler(NewPlaneMovement);
        TimerTask.Interval = new TimeSpan(0, 0, 0, 0, 10);
        TimerTask.Start();

    }

    int NewPlaneTop;
    int newPlaneBottom;
    int newPlaneLeft;
    int newPlaneRight;

    private void NewPlaneMovement(object sender, EventArgs e)
    {

        Dispatcher.BeginInvoke(() =>
            GetUiData() );

        Dispatcher.BeginInvoke(() =>
            SetUiData());






        PlaneFlight = PlaneFlight - 1;

        if (PlaneFlight < -10)
        {
            PlaneFlight = -10;
        }
    }

    private void SetUiData()
    {
        double NewTop = Convert.ToDouble(NewPlaneTop - PlaneFlight);
        PlaneObj.Margin = new Thickness(newPlaneLeft, NewTop, newPlaneRight, newPlaneBottom);
    }

    private void GetUiData()
    {
        NewPlaneTop = Convert.ToInt32(PlaneObj.Margin.Top);
        newPlaneBottom = Convert.ToInt32(PlaneObj.Margin.Bottom);
        newPlaneLeft = Convert.ToInt32(PlaneObj.Margin.Left);
        newPlaneRight = Convert.ToInt32(PlaneObj.Margin.Right);
    }

Upvotes: 1

Views: 1044

Answers (2)

vITs
vITs

Reputation: 1560

Dispatcher.BeginInvoke() is used only if you are doing changes which you want to happen on main UI thread i.e. modifying UI at run-time as showing ProgressBar when there is another thread (may be main thread) is going on.

Call DoSomething directly without using any thread. Also, call SetUiData directly but modify function like this:

private void SetUiData()
{
    double NewTop = Convert.ToDouble(NewPlaneTop - PlaneFlight);
    Dispatcher.BeginInvoke(() =>
        PlaneObj.Margin = new Thickness(newPlaneLeft, NewTop, newPlaneRight, newPlaneBottom);
    }
}

And finally call GetUiData directly without Dispatcher.BeginInvoke() and use function as it is as no ui is modified in that function. Hope this helped to clear your understanding.

Upvotes: 2

Sami Kuhmonen
Sami Kuhmonen

Reputation: 31143

The idea of the DispatcherTimer is that you start it in the main thread and it fires in the main thread also. So don't create any threads, just create the DispatcherTimer. You won't need Dispatcher.BeginInvoke() either, since the tick will be in the main thread.

Upvotes: 0

Related Questions