该应用程序称为为不同线程编组的接口--Windows Store App

Yec*_*ats 51 c# xaml multithreading windows-store-apps

所以,首先我已经阅读了大量关于这个特定问题的线索,我仍然不明白如何解决它.基本上,我正在尝试与websocket进行通信,并将收到的消息存储在绑定到listview的可观察集合中.我知道我正在从套接字中正确地获得响应,但是当它尝试将其添加到observable集合时,它会给我以下错误:

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

我已经阅读了一些关于"发送"以及其他一些事情的信息,但我只是大肆混淆!这是我的代码:

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

    }
Run Code Online (Sandbox Code Playgroud)

这是绑定:

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

如何在仍然绑定到listview的observable集合时使错误消失?

小智 115

这解决了我的问题:

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

在Windows应用商店应用中获取CoreDispatcher的正确方法

  • 这相当于runOnUiThread for Android http://developer.android.com/reference/android/app/Activity.html#runOnUiThread(java.lang.Runnable) (6认同)
  • 不敢相信,这是我的确切问题,在搜索了整个“异常”消息之后,它在Google搜索结果中排名第一。好一个! (2认同)
  • 我对C#和Windows开发非常陌生,但这是一个很长的方法调用链,感觉就像是黑客。有一个更好的方法吗? (2认同)

Bal*_*ick 7

尝试更换

messageList.Add(read); 
Run Code Online (Sandbox Code Playgroud)

Dispatcher.Invoke((Action)(() => messageList.Add(read)));
Run Code Online (Sandbox Code Playgroud)

如果您从Window类外部调用,请尝试:

Application.Current.Dispatcher.Invoke((Action)(() => messageList.Add(read)));
Run Code Online (Sandbox Code Playgroud)

  • 在页面上(或在任何DependencyObject中)使用时,调用Dispatcher.RunAsync(()=> messageList.Add(read)); 在其他地方调用Window.Current.Dispatcher.RunAsync(()=> messageList.Add(read)); (2认同)

Mel*_*per 6

对基于任务的异步方法稍作修改,但不会等待此处的代码。

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

此代码将等待,并允许您返回一个值:

    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;
    }
Run Code Online (Sandbox Code Playgroud)

而在安卓上:

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

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

        return await taskCompletionSource.Task;
    }
Run Code Online (Sandbox Code Playgroud)