c# - 应用程序调用了为不同线程编码的接口(interface) - Xamarin Forms

标签 c# multithreading wcf xamarin xamarin.forms

我在加载给定页面时通过 WCF 加载一些数据。然后,我想在数据加载后用值填充选取器。但是,我遇到了交叉线程问题。这是代码:

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 中,我收到的错误是

其他信息:应用程序调用了为不同线程编码的接口(interface)。 (HRESULT 异常:0x8001010E (RPC_E_WRONG_THREAD))

我猜我正在以一种意想不到的方式使用 OnAppearing 调用,那么我应该如何解决这个问题?当页面开始加载时,我需要进行基于任务的异步 WCF 调用。

在 iOS 上,我没有收到错误消息。

最佳答案

您的问题来自

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.StartNewGetRecordsAsync 已经是一个异步方法。 Initialise(原文如此)中的大部分延迟很可能来自 I/O 延迟。

从另一个线程运行Initialise只会增加运行时间,因为数据需要跨线程进行编码(marshal)以及同步。

不如尝试一下。

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

关于c# - 应用程序调用了为不同线程编码的接口(interface) - Xamarin Forms,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41994891/

相关文章:

.net - 可移植 WCF 测试客户端 10 (Visual Studio 2010)

c# - 应用程序在处理所有事件之前退出 - 基于事件的异步模式

c# - Java+Swing 比 C#+WinForms/WPF 有什么优势?

c# - linq 中使用 ObjectSet<> 而不是使用 .AddToXXXXX(MyEntity) 插入记录的语法是什么,因为这已被弃用?

c# - WWW POST 给我内部服务器错误

C++线程 - 并行处理

python - 在 Django/mod_wsgi 中进行一次性初始化的安全方法是什么?

wcf - Wcf 服务中的错误 SPContext

Java - 线程状态异常

c# - 在 Visual Studio 2010 中添加服务引用似乎不起作用