使用Dispatcher.BeginInvoke()时,为什么会出现“无效的跨线程访问”?

时间:2014-05-24 22:55:32

标签: c# multithreading windows-phone-8 dispatcher

我正在寻找改善我的应用程序性能的方法,并且正在努力解决问题。我想要从另一个线程更新UI,从我可以收集的内容我应该使用Dispatcher.BeginInvoke,但是当我运行下面的代码时,我得到一个关于无法访问其他线程的错误。任何想法?

错误为An Unhandled exception of type 'System.UnauthorizedAccessException' occurred in System.Windows.ni.dll

其他信息:无效的跨线程访问。"

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);
    }

2 个答案:

答案 0 :(得分:2)

Dispatcher.BeginInvoke()仅在您正在进行主UI线程上发生的更改时使用,即在运行时修改UI,以便在有另一个线程(可能是主线程)时显示ProgressBar。

直接调用DoSomething而不使用任何线程。另外,直接调用SetUiData但修改函数如下:

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

最后在没有GetUiData的情况下直接调用Dispatcher.BeginInvoke()并使用函数,因为在该函数中没有修改ui。希望这有助于清除您的理解。

答案 1 :(得分:0)

DispatcherTimer的想法是你在主线程中启动它,它也在主线程中触发。所以不要创建任何线程,只需创建DispatcherTimer。您也不需要Dispatcher.BeginInvoke(),因为勾号将位于主线程中。