#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. Приветствия!!