该应用程序调用了一个为不同线程编组的接口 - Xamarin Forms
Posted
技术标签:
【中文标题】该应用程序调用了一个为不同线程编组的接口 - Xamarin Forms【英文标题】:The application called an interface that was marshalled for a different thread - Xamarin Forms 【发布时间】:2017-06-19 02:12:32 【问题描述】:我在加载给定页面时通过 WCF 加载一些数据。然后,我想在数据加载后用值填充 Picker。但是,我遇到了跨线程问题。代码如下:
protected async override void OnAppearing()
base.OnAppearing();
await Task.Factory.StartNew(async () => await Initialise(); );
private async Task Initialise()
var activities = await App.XivicServicesClient.DataAccessCalls.GetRecordsAsync<ActivityDef>(null, new ConnectionInfo(null, App.XivicServicesClient.AuthToken));
var activityCodes = activities.Select(a => a.Code);
foreach (var activityCode in activityCodes)
ActivityPicker.Items.Add(activityCode);
在 Windows UWP 中,我得到的错误是
附加信息:应用程序调用了为不同线程编组的接口。 (来自 HRESULT 的异常:0x8001010E (RPC_E_WRONG_THREAD))
我想我正在以一种意想不到的方式使用 OnAppearing 调用,那么我应该如何解决这个问题?我需要在页面开始加载时进行基于任务的异步 WCF 调用。
在 ios 上,我没有收到错误消息。
【问题讨论】:
如前所述,您不应在此处使用Task.Factory.StartNew
。更何况Task.Factory.StartNew
是一种危险的方法;即使您想要在后台线程上运行代码,也几乎不应该使用它(改用Task.Run
)。
【参考方案1】:
你的问题来自于
ActivityPicker.Item.Add(activityCode);
该行只能在 UI 线程上运行。
您可以使用以下方法轻松修复此代码
protected async override void OnAppearing()
base.OnAppearing();
var activityCodes = await Task.Factory.StartNew(async () => await Initialise(); );
foreach (var activityCode in activityCodes)
ActivityPicker.Items.Add(activityCode);
private async Task<List<string>> Initialise()
var activities = await App.XivicServicesClient
.DataAccessCalls
.GetRecordsAsync<ActivityDef>(null, new ConnectionInfo(null, App.XivicServicesClient.AuthToken));
return activities.Select(a => a.Code).ToList();
但是,我真的怀疑您“需要”使用Task.Factory.StartNew
。 GetRecordsAsync
已经是一个异步方法。 Initialise
(sic) 中的大部分延迟可能来自 I/O 延迟。
从另一个线程运行 Initialise
只会增加运行时间,因为数据需要跨线程封送以及同步。
不如试试吧。
protected async override void OnAppearing()
base.OnAppearing();
var activities = await App.XivicServicesClient
.DataAccessCalls
.GetRecordsAsync<ActivityDef>(null, new ConnectionInfo(null, App.XivicServicesClient.AuthToken));
foreach (var activityCode in activities.Select(a => a.Code))
ActivityPicker.Items.Add(activityCode);
【讨论】:
这里有很多很棒的信息。您对我从反复试验中得出的结论给出了很好的解释。【参考方案2】:问题很简单。我添加了不必要的代码,而该代码导致了该错误。下面是固定方法:
protected async override void OnAppearing()
base.OnAppearing();
await Initialise();
【讨论】:
以上是关于该应用程序调用了一个为不同线程编组的接口 - Xamarin Forms的主要内容,如果未能解决你的问题,请参考以下文章
应用程序调用了为不同线程编组的接口 - Windows Store App
通过非默认 AppDomain 中的 C# 函数调用编组 C++ 指针接口
创建 COM 接口,返回一个在 C# 中编组为 IntPtr 的指针