C# 该应用程序调用了一个为不同线程编组的接口 - Windows 应用商店应用程序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19341591/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 14:47:40  来源:igfitidea点击:

The application called an interface that was marshalled for a different thread - Windows Store App

c#multithreadingxamlwindows-store-apps

提问by Yecats

So, first I have read a ton of threads on this particular problem and I still do not understand how to fix it. Basically, I am trying to communicate with a websocket and store the message received in an observable collection that is bound to a listview. I know that I am getting a response back properly from the socket, but when it tries to add it to the observable collection it gives me the following error:

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

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

I've read some information on "dispatch" as well as some other things, but I am just massively confused! Here is my 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

    }

And this is the binding:

这是绑定:

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

How do I make the error go away while still binding to the observable collection for my listview?

如何在仍然绑定到我的列表视图的可观察集合的同时使错误消失?

采纳答案by various

This solved my issue:

这解决了我的问题:

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

Correct way to get the CoreDispatcher in a Windows Store app

在 Windows Store 应用程序中获取 CoreDispatcher 的正确方法

回答by Baldrick

Try replacing

尝试更换

messageList.Add(read); 

with

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

If you're calling from outside your Window class, try:

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

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

回答by Melbourne Developer

Slight modification for task based async methods but the code in here will not be awaited.

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

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

This code WILL await, and will allow you to return a value:

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

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

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