尽管使用了调度程序,但无法进行跨线程访问

时间:2012-12-14 13:27:27

标签: c# xaml windows-phone

我已经了解了我遇到的这个问题,我似乎无法找到解决方案。有些人建议使用调度程序将代码执行推送到UI线程。但这并不能解决我的问题。我从Asyc方法调用此代码,该方法由Guide对象调用,以显示通知。控制UI内容的代码如下:

public bool isDisabled
{
    set
    {
        if (value)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    color = new SolidColorBrush(Colors.Gray);
                });
            enabled = false;
        }
        else
        {
            Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    color = origionalColor;
                });
            enabled = true;
        }
    }
}

正在从

调用它
    private void nameInputFinished(IAsyncResult ar)
    {
        int? result = Guide.EndShowMessageBox(ar);

        if (result == 0)
        {
             [...]

             JourneyPanels.getPanel(JourneyPanelTypes.integration).isDisabled = false;
        }
    }

不确定为什么我得到了corss-thread异常,但我很确定它与async方法嵌套有关。

非常感谢任何帮助!

编辑:完全异常堆栈

  {System.UnauthorizedAccessException: Invalid cross-thread access.
  at MS.Internal.XcpImports.CheckThread()
  at MS.Internal.XcpImports.SetValue(IManagedPeerBase obj, DependencyProperty property, Boolean b)
  at System.Windows.DependencyObject.SetValue(DependencyProperty property, Boolean b)
  at System.Windows.Controls.TextBox.set_IsReadOnly(Boolean value)
  at PocketRitual.Journey.nameInputFinished(IAsyncResult ar)
  at Microsoft.Xna.Framework.GamerServices.ActionDialogHelper.Complete()
  at Microsoft.Xna.Framework.GamerServices.ActionDialogHelper.GetMessageBoxResult(Object state)
  at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
  at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
  at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
  at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
  at System.Threading.ThreadPoolWorkQueue.Dispatch()
  at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()}

2 个答案:

答案 0 :(得分:4)

这是您需要在主UI线程上运行的调用代码,例如。

Deployment.Current.Dispatcher.BeginInvoke(() => {
    JourneyPanels.getPanel(JourneyPanelTypes.integration).isDisabled = false;
});

您无需在内部属性更改上调用Dispatcher,因为此时您将在UI线程上运行。

答案 1 :(得分:1)

您没有包含完整的代码,让人们猜测。我非常怀疑isDisabled(BTW,在.NET世界中我们用大写字母命名属性)例如只有一个setter。我还打赌这用于数据绑定,因此setter有额外的代码来引发PropertyChanged事件。最好的猜测是在后台线程而不是UI线程上引发了PropertyChanged事件。设计明智,最好不要隐藏在酒店内。当你不在后台线程中时,它会增加不必要的开销。当后台线程执行任何会影响UI的操作时,包括更改数据绑定的属性,应该通过后台线程中的调度程序调用该操作。