#c# #xamarin #uwp #realm #synchronizationcontext
Вопрос:
Я работаю над переходом с SQLite/WebAPIs на Realms в приложении в формах Xamarin.
Это приложение управляет службой обмена сообщениями (чат через SignalR).
Проблема, которая возникла, заключается в том, что при получении сообщения, которое я пытаюсь сохранить в базе данных, приложение неожиданно выходит из строя. (Вопрос, которого не было с SQLite).
Я получаю знаменитую ошибку: область, доступ к которой осуществляется неправильно, точно, когда 3-е или 4-е сообщение пытается вставить, было немного сложно увидеть точный момент.
Как я мог прочитать, как в вопросах прямо здесь, на Stackoverflow, так и в GitHub области Dot-Net. доступ к экземпляру должен осуществляться в том же потоке, в котором он был создан.
Как они предполагают, один из способов добиться этого-использовать правильный контекст синхронизации через AsyncContext.Run
Nito.AsyncEx Стивена Клири или Device.BeginInvokeOnMainThread
.
Я задаю этот вопрос, потому что, к сожалению, я занимаюсь темой потоков и задач на базовом уровне, каким образом я должен подходить к предыдущим предложениям в своем коде? или что я должен правильно настроить, чтобы получить доступ к потоку, в котором он был создан?
Это мой код:
LobbyViewModel
public LobbyViewModel()
{
ChatService.OnReceivePrivateMessage = ChatService_OnReceivePrivateMessage;
}
private async void ChatService_OnReceivePrivateMessage(object sender, MessageEventArgs args)
{
await SendMessage(…);
}
private async Task SendMessage(…)
{
await UpdateMetaData(…);
}
public async Task UpdateMetaData(…)
{
await ManagerService.InsertMetaDataChatAsync(metaDataChat);
}
ManagerService
public async Task InsertMetaDataChatAsync (MetaDataChatModel MetaDataChatModel)
{
IMetaDataChatServices MetaDataChatServices = App.AppContainer.Resolve<IMetaDataChatServices>();
IResponse DataResult = (await MetaDataChatServices.Insert(MetaDataChatModel));
}
Repository
public async Task<IResponse> CreateAsync(MetaDataChatModel MetaDataChatModel)
{
MetaDataChatModel.Id = Guid.NewGuid().ToString();
MetaDataChatModel.Partition = _realmManager.projectPartition;
var MetaDataChatDto = MetaDataChatModel.ToDto();
var realmInstance = await _realmManager.GetInstanceAsync();
if (realmInstance == null)
return new Response(false, "Realm instance can't be null");
await realmInstance.WriteAsync(realm =>
{
realm.Add(MetaDataChatDto, false);
});
return new Response(true);
}
RealmManager
public RealmManager()
{
RealmApp = App.Create(appId);
//DataBase = Realms.Realm.GetInstance(syncConfig);
}
public Task<Realms.Realm> GetInstanceAsync()
{
return Realms.Realm.GetInstanceAsync(syncConfig);
}
public async Task RealmLogInAsync()
{
if (RealmApp.CurrentUser == null)
{
User user = await RealmApp.
LogInAsync(Credentials.EmailPassword("email", "password"));
if (user == null)
{
return;
}
}
projectPartition = $"project={RealmApp.CurrentUser.Id}";
syncConfig = new SyncConfiguration(projectPartition, RealmApp.CurrentUser);
}
public async Task RealmLogOutAsync()
{
if (RealmApp != null amp;amp; RealmApp.CurrentUser!=null)
{
await RealmApp.CurrentUser?.LogOutAsync();
}
}
Комментарии:
1. Привет @Ivanrlg ваш код немного сбивает с толку. Можете ли вы выделить в своем фрагменте кода, в какой момент вы получаете исключение?
2. ПРИВЕТ @papafe Я пытаюсь немного привести его в порядок. исключение происходит здесь:
public async Task <IResponse> CreateAsync (MetaDataChatModel MetaDataChatModel)
. Я думаю, что в какой-то момент он не закончил вставку, когда вставляется другой поток, и происходит сбой.3. @ Ivanrlg, просто чтобы убедиться, что у
CreateAsync
тебя естьrealm.Add(MetaDataChatDto)
. Это на самом делеrealmInstance.Add(MetaDataChatDto)
или я что-то упускаю?4. Привет @papafe, это риэлм. Добавить(МетаДатаЧатьДто, ложь);. используйте область внутри. ссылка отсюда: [ссылка] docs.mongodb.com/realm-legacy/docs/dotnet/latest/api/reference/…
5. ах да, извините, я неправильно понял, мой плохой! 🙂