0

私が抱えているこの問題について読みましたが、解決策が見つからないようです。一部の人々は、ディスパッチャを使用してコード実行を UI スレッドにプッシュすることを推奨しています。しかし、これは私の問題を解決しません。通知を表示するために Guide オブジェクトによって事前に呼び出される Asyc メソッドからこのコードを呼び出しています。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例外が発生する理由はわかりませんが、非同期メソッドのネストと関係があると確信しています。

どんな助けでも大歓迎です!

編集:完全な例外スタック

  {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 に答える