Формы Xamarin — область, доступ к которой осуществляется из неправильного потока

#xamarin.forms #realm #mvvm-light #.net-standard-2.0 #zxing.net

#xamarin.forms #область #mvvm-light #.net-стандарт-2.0 #zxing.net

Вопрос:

Возможно, я упускаю здесь что-то действительно простое, но все равно спрошу…..

Я использую Xamarin forms (.NET Standard project), MVVMLight, Realm DB и сканер штрих-кодов ZXing.

У меня есть realmobject, подобный этому…

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

Все вышеперечисленное работает нормально, и у меня нет проблем с этим. В той же viewmodel я также могу запустить сканер ZXing и отсканировать штрих-код, представляющий регистрационный код.

Это, в свою очередь, заполняет приведенное ниже свойство (также в viewmodel) после сканирования…

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

и вызывает приведенный ниже метод (подключенный через ScanResultCommand) для извлечения участника, имеющего отсканированный регистрационный код.

     private async Task ScanResults()
    {
        if (Result != null amp;amp; !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
            }
        }
    }
  

Я продолжаю получать приведенную ниже ошибку….

Система.Исключение: Область, доступ к которой осуществляется из неправильного потока.

генерируется строкой ниже….

Выбранный участник = Участники.FirstOrDefault(p => p.RegistrationCode.Equals(regCode, сравнение строк.OrdinalIgnoreCase));

Я не уверен, что это неправильный поток, но любые идеи о том, как я могу обойти получение отсканированного участника либо из уже заполненного IQueryable, либо из представления Realm напрямую, были бы высоко оценены.

Спасибо

Ответ №1:

Да, вы получаете экземпляр области в конструкторе, а затем используете его из асинхронной задачи (или потока). Вы можете получить доступ к области только из потока, в котором вы получили ссылку. Поскольку вы используете только экземпляр по умолчанию, вы должны иметь возможность просто получить локальную ссылку внутри функции (или потока), в которой вы ее используете. Попробуйте использовать

     Realm LocalInstance = Realms.Realm.GetInstance();
  

в верхней части функции и используйте это. Вам нужно будет воссоздать Participants запрос, чтобы использовать тот же экземпляр, что и его источник. Это будет иметь место везде, где вы используете асинхронные задачи (потоки), поэтому либо измените все, чтобы получить экземпляр по умолчанию при входе, либо уменьшите количество потоков, которые обращаются к области.

Кстати, я удивлен, что вы не получаете аналогичную ошибку доступа изнутри
RefreshParticipants()
— возможно, вы на самом деле не получаете доступ к данным через RealmInstance оттуда.

Комментарии:

1. Спасибо за ваш ответ. Получение отдельного локального экземпляра области не сработало, поскольку у меня были другие фрагменты кода, использующие IQueryable<Участник>, и я продолжал получать ту же ошибку. Однако первое предложение в вашем ответе помогло мне прийти к решению. Я удалил сигнатуру ‘async Task’ из RefreshAttendees (), поскольку она была избыточной, т. Е. не вызывал ее с помощью await где-либо еще. Благодаря этому RealmInstance теперь работает в MainThread, поэтому я использовал Device. BeginInvokeOnMainThread в методе ScanResults. Это заставило его работать. Помечаем ваш ответ как answer. Приветствия!!