0

我已经阅读了我遇到的这个问题,但我似乎无法找到解决方案。有人建议使用调度程序将代码执行推送到 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;
        }
    }

不知道为什么我得到了跨线程异常,但我很确定它与异步方法嵌套有关。

任何帮助是极大的赞赏!

编辑:完整的异常堆栈

  {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()}
4

2 回答 2

4

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

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

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

于 2012-12-14T13:34:56.690 回答
1

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

于 2012-12-14T13:51:46.223 回答