L'application a appelé une interface qui a été formé pour un autre thread-Windows Store App

Alors, tout d'abord j'ai lu une tonne de fils sur ce problème particulier et je ne comprends toujours pas comment le résoudre. En gros, j'essaie de communiquer avec un websocket et de stocker le message reçu dans une collection observable qui est liée à un listview. Je sais que je reçois une réponse correctement du support, mais lorsqu'il essaie de l'ajouter à la collection observable, il me donne l'erreur suivante:

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

j'ai lu des informations sur "dispatch" ainsi que quelques autres choses, mais je suis juste massivement confus! Voici mon code:

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

    }

Et voici la liaison:

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

Comment faire pour que l'erreur disparaisse tout en restant liée à la collection observable de mon listview?

43
demandé sur Yecats 2013-10-13 07:35:53

3 réponses

cela a résolu mon problème:

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

Comment obtenir le CoreDispatcher dans un magasin Windows app

96
répondu various 2014-12-30 00:34:31

essayer de remplacer

messageList.Add(read); 

avec

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

si vous appelez de l'extérieur de votre classe fenêtre, essayez:

Application.Current.Dispatcher.Invoke((Action)(() => messageList.Add(read)));
7
répondu Baldrick 2013-10-14 05:36:27

légère modification pour les méthodes async basées sur les tâches mais le code ici ne sera pas attendu.

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

ce code attendra, et vous permettra de retourner une valeur:

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

et sur 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;
    }
1
répondu Melbourne Developer 2018-03-19 09:11:08