应用程序调用了为不同线程编组的接口 - Windows Store App
Posted
技术标签:
【中文标题】应用程序调用了为不同线程编组的接口 - Windows Store App【英文标题】:The application called an interface that was marshalled for a different thread - Windows Store App 【发布时间】:2019-12-26 22:59:02 【问题描述】:所以,首先我已经阅读了大量关于这个特定问题的线程,但我仍然不明白如何解决它。基本上,我正在尝试与 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;
如何在仍然绑定到我的列表视图的可观察集合的同时使错误消失?
【问题讨论】:
【参考方案1】:这解决了我的问题:
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
【讨论】:
仅供参考,这相当于 android 的 runOnUiThread developer.android.com/reference/android/app/… python中有没有等价物? 不敢相信,这是我的确切问题,在搜索整个异常消息后,它在 Google 搜索结果中排名第一。不错! @nickpick - 不是真的...这解决了 C# 中 Windows 应用程序的一个非常具体的问题。 我对 C# 和 Windows 开发非常陌生,但这是一个很长的方法调用链,感觉就像是 hack。有没有更好的方法来做到这一点?【参考方案2】:尝试替换
messageList.Add(read);
与
Dispatcher.Invoke((Action)(() => messageList.Add(read)));
如果您是从 Window 类外部调用,请尝试:
Application.Current.Dispatcher.Invoke((Action)(() => messageList.Add(read)));
【讨论】:
Dispatcher 位于哪个命名空间中?它转为“System.ServiceModel.Dispatcher”,但 Invoke 不是它的一种方法。 在页面(或任何 DependencyObject)中使用时,调用 Dispatcher.RunAsync(() => messageList.Add(read));在其他地方调用 Window.Current.Dispatcher.RunAsync(() => messageList.Add(read));【参考方案3】:对基于任务的异步方法稍作修改,但不会等待此处的代码。
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;
【讨论】:
【参考方案4】:也许这不是一个“好”的做法,但它确实有效。我从 webSocket 向 mainBody 实例留言,在那里我有一个定时阅读器...
public class C_AUTHORIZATION
public Observer3.A_MainPage_cl parentPageInstance; //еще одни экземпляр родителя
public WebSocket x_Websocket;
private string payload = "";
private DateTime nowMoment = DateTime.Now;
public void GET_AUTHORIZED()
bitfinex_Websocket= new WebSocket("wss://*****.com/ws/2");
var apiKey = "";
var apiSecret = "";
DateTime nowMoment = DateTime.Now;
payload = "";
x_Websocket.Opened += new EventHandler(websocket_Opened);
x_Websocket.Closed += new EventHandler(websocket_Closed);
void websocket_Opened(object sender, EventArgs e)
x_Websocket.Send(payload);
parentPageInstance.F_messager(payload);
void websocket_Closed(object sender, EventArgs e)
parentPageInstance.F_messager("L106 websocket_Closed!");
GET_AUTHORIZED();
public sealed partial class A_MainPage_cl : Page
DispatcherTimer ChartsRedrawerTimer;
public bool HeartBeat = true;
private string Message;
public A_MainPage_cl()
this.InitializeComponent();
ChartsRedrawerTimer = new DispatcherTimer() Interval = new TimeSpan(0, 0, 0, 0, 100) ;
ChartsRedrawerTimer.Tick += Messager_Timer;
ChartsRedrawerTimer.Start();
private void Messager_Timer(object sender, object e)
if(Message !=null) //
F_WriteLine(Message);
Message = null; //
public void F_messager(string message) //
Message = message;
【讨论】:
以上是关于应用程序调用了为不同线程编组的接口 - Windows Store App的主要内容,如果未能解决你的问题,请参考以下文章
该应用程序调用了一个为不同线程编组的接口 - Xamarin Forms
将 COM 接口编组到多个线程时,克隆流是不是足够,还是需要复制?
通过非默认 AppDomain 中的 C# 函数调用编组 C++ 指针接口