web-dev-qa-db-ja.com

アプリケーションが別のスレッド用にマーシャリングされたインターフェイスを呼び出しました-Windowsストアアプリ

そのため、最初にこの特定の問題に関する大量のスレッドを読みましたが、まだ修正方法がわかりません。基本的に、私はwebsocketと通信し、受信したメッセージをリストビューにバインドされた監視可能なコレクションに保存しようとしています。私はソケットから適切に応答を取得していることを知っていますが、それを監視可能なコレクションに追加しようとすると、次のエラーが表示されます:

The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))

「ディスパッチ」に関する情報やその他の情報を読んだことがありますが、混乱しているだけです。ここに私のコードがあります:

public ObservableCollection<string> messageList  { get; set; }
private void MessageReceived(MessageWebSocket sender, MessageWebSocketMessageReceivedEventArgs args)
    {
        string read = "";
        try
        {
            using (DataReader reader = args.GetDataReader())
            {
                reader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
                read = reader.ReadString(reader.UnconsumedBufferLength);
            }
        }
        catch (Exception ex) // For debugging
        {
            WebErrorStatus status = WebSocketError.GetStatus(ex.GetBaseException().HResult);
            // Add your specific error-handling code here.
        }


        if (read != "")
           messageList.Add(read); // this is where I get the error

    }

そして、これはバインディングです:

protected override async void OnNavigatedTo(NavigationEventArgs e)
{
    //await Authenticate();
    Gameboard.DataContext = Game.GameDetails.Singleton;
    lstHighScores.ItemsSource = sendInfo.messageList;
}

リストビューの観察可能なコレクションにバインドしている間にエラーを解消するにはどうすればよいですか?

50
Yecats

これは私の問題を解決しました:

Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
    {
        // Your UI update code goes here!
    }
);

WindowsストアアプリでCoreDispatcherを取得する正しい方法

113
various

交換してみてください

messageList.Add(read); 

Dispatcher.Invoke((Action)(() => messageList.Add(read)));

Windowクラスの外部から呼び出している場合は、次を試してください。

Application.Current.Dispatcher.Invoke((Action)(() => messageList.Add(read)));
7
Baldrick

タスクベースの非同期メソッドのわずかな変更ですが、ここのコードは待たれません。

await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
    // Your UI update code goes here!
}
).AsTask();

このコードは待っており、値を返すことができます:

    private async static Task<string> GetPin()
    {
        var taskCompletionSource = new TaskCompletionSource<string>();

        CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
        async () =>
        {
            var pin = await UI.GetPin();
            taskCompletionSource.SetResult(pin);
        }
        );

        return await taskCompletionSource.Task;
    }

Androidの場合:

    private async Task<string> GetPin()
    {
        var taskCompletionSource = new TaskCompletionSource<string>();

        RunOnUiThread(async () =>
        {
            var pin = await UI.GetPin();
            taskCompletionSource.SetResult(pin);
        });

        return await taskCompletionSource.Task;
    }
2