Xamarin 表单 - 从不正确的线程访问的领域

Posted

技术标签:

【中文标题】Xamarin 表单 - 从不正确的线程访问的领域【英文标题】:Xamarin forms - Realm accessed from incorrect thread 【发布时间】:2019-08-04 19:17:54 【问题描述】:

也许我在这里遗漏了一些非常简单的东西,但无论如何我都会问.....

我正在使用 Xamarin 表单(.NET 标准项目)、MVVMLight、Realm DB 和 ZXing Barcode Scanner。

我有一个像这样的领域对象...

public class Participant : RealmObject

    public string FirstName get; set;
    public string LastName get; set;
    public string Email get; set;
    public string RegistrationCode get; set;

    //More properties skipped out for brevity

我对应的viewmodel如下:

public class ParticipantViewModel

    Realm RealmInstance
    public ParticipantViewModel()
    
        RealmInstance = Realms.Realm.GetInstance();
        RefreshParticipants();
    

    private async Task RefreshParticipants() 
    
        //I have code here that GETS the list of Participants from an API and saves to the device.
        //I am using the above-defined RealmInstance to save to IQueryable<Participant> Participants
    

以上所有工作都很好,我对此没有任何问题。在同一个视图模型中,我还能够启动 ZXing 扫描仪并扫描代表 RegistrationCode 的条形码。

这反过来会在扫描后填充以下属性(也在视图模型中)...

    private ZXing.Result result;
    public ZXing.Result Result
    
        get  return result; 
        set  Set(() => Result, ref result, value); 
    

并调用以下方法(通过 ScanResultCommand 连接)以获取带有扫描的 RegistrationCode 的参与者。

    private async Task ScanResults()
    
        if (Result != null && !String.IsNullOrWhiteSpace(Result.Text))
        
            string regCode = Result.Text;
            await CloseScanner();
            SelectedParticipant = Participants.FirstOrDefault(p => p.RegistrationCode.Equals(regCode, StringComparison.OrdinalIgnoreCase));
            if (SelectedParticipant != null)
            
                //Show details for the scanned Participant with regCode
            
            else
            
                //Display not found message
            
        
    

我不断收到以下错误....

System.Exception:从错误线程访问的领域。

由下面的行生成....

SelectedParticipant = Participants.FirstOrDefault(p => p.RegistrationCode.Equals(regCode, StringComparison.OrdinalIgnoreCase));

我不确定这是一个不正确的线程,但如果我能从已经填充的 IQueryable 或直接从 Realm 表示中获取扫描的参与者的任何想法,将不胜感激。

谢谢

【问题讨论】:

【参考方案1】:

是的,您在构造函数中获取了一个领域实例,然后从异步任务(或线程)中使用它。您只能从获得引用的线程访问领域。由于您只使用默认实例,因此您应该能够简单地在使用它的函数(或线程)中获取本地引用。尝试使用

    Realm LocalInstance = Realms.Realm.GetInstance();

在函数的顶部并使用它。您还需要重新创建 Participants 查询以使用相同的实例作为其源。无论您使用异步任务(线程),都会出现这种情况,因此要么更改所有以获取进入时的默认实例,要么减少访问领域的线程数。

顺便说一句,我很惊讶您没有从 RefreshParticipants() 中收到类似的访问错误 - 也许您实际上并没有从那里通过 RealmInstance 访问数据。

【讨论】:

感谢您的回复。获取领域的单独本地实例不起作用,因为我使用 IQueryable 有其他代码位,并且我一直收到相同的错误。但是,您回复中的第一句话帮助我找到了解决方案。我从 RefreshAttendees() 中删除了“异步任务”签名,因为它是多余的,即不在其他任何地方使用 await 调用它。有了这个 RealmInstance 现在在 MainThread 上运行,所以我在 ScanResults 方法中使用了 Device.BeginInvokeOnMainThread。这让它发挥作用。将您的回复标记为答案。干杯!!

以上是关于Xamarin 表单 - 从不正确的线程访问的领域的主要内容,如果未能解决你的问题,请参考以下文章

从不正确的线程访问的领域 - 调度异步

在 IntentService 和 AsyncTask (Android) 之间使用共享代码时,领域“从不正确的线程访问”错误

Xamarin表单 - 从错误的线程访问的域

在 Xamarin Android 中访问 UI 线程

为 Xamarin 表单设置正确的图像尺寸

绑定 xamarin 表单选择器值的正确方法