c# - 如何在 .NET (Xamarin-UWP) 中创建的同一线程中访问 Realm 实例?
问题描述
我正在Xamarin Forms 中的应用程序中从 SQLite/ WebApis迁移到领域。
此应用程序管理消息传递服务(通过 SignalR 聊天)。
出现的问题是当收到一条消息时,我尝试将其存储在数据库中,应用程序意外崩溃。(SQLite 没有发生的问题)。
我收到了著名的错误:从不正确访问的领域,正是在尝试插入第三条或第四条消息时,很难看到确切的时刻。
正如我所读到的,无论是在 Stackoverflow 上的问题中,还是在 Dot-Net Realm GitHub 上的问题中。必须在创建它的同一线程中访问该实例。
正如他们所建议的那样,实现此目的的一种方法是通过 Stephen Cleary 的 Nito.AsyncEx 使用正确的SynchronizationContext或.AsyncContext.Run
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 && RealmApp.CurrentUser!=null)
{
await RealmApp.CurrentUser?.LogOutAsync();
}
}