【发布时间】:2020-05-04 19:32:32
【问题描述】:
我正在开发一个字典应用程序,它具有许多相互连接的表,因此当用户进行查询时,应用程序会搜索几乎所有这些表及其许多字段,这会导致对数据库的大量查询和 UI 冻结。
那么,如何在每次使用结果更新 UI 时异步地在单独的任务中进行这些查询?
我已经看到了适用于 android 版本领域的 findAllAsync 等,但对于 .net,我找不到任何替代方案,我每次运行异步时都尝试按照其他地方的建议重新初始化数据库,但不知何故它没有t 工作并给我同样的错误。
System.Exception: 'Realm accessed from incorrect thread.'
当我尝试将领域结果转换为普通列表以在 UI 上处理时,在 ToList() 上引发错误,请帮助解决此问题
这是我的代码
using Data.Models;
using Microsoft.EntityFrameworkCore.Internal;
using Realms;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Data
{
public class RealmAsync
{
IQueryable<Entry> Entries { get; set; }
public async void Run()
{
Realm RealmDatabase = Realm.GetInstance();
Entries = RealmDatabase.All<Entry>();
var entries = await FindAsync("а", Entries);
Console.WriteLine($"async result async {entries.Count()}");
}
public async Task<IEnumerable<Entry>> FindAsync(string needle, IQueryable<Entry> haystack)
{
var foregroundRealm = Realm.GetInstance();
var haystackRef = ThreadSafeReference.Create<Entry>(haystack);
var filteredEntriesRef = await Task.Run(() =>
{
using (var realm = Realm.GetInstance())
{
var bgHaystack = realm.ResolveReference(haystackRef);
return ThreadSafeReference.Create(bgHaystack.Where(entry => entry.Content.ToLower().StartsWith(needle)));
}
});
var result = foregroundRealm.ResolveReference(filteredEntriesRef).ToArray();
return result;
}
}
入门模型类:
using System.ComponentModel.DataAnnotations.Schema;
using Realms;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System;
namespace Data.Models
{
[Table("entry")]
public class Entry : RealmObject
{
public class EntryType
{
public const byte Word = 1;
public const byte Phrase = 2;
public const byte Text = 3;
};
[Key]
[PrimaryKey]
[Column("entry_id")]
public int Id { get; set; }
[Column("user_id")]
public int UserId { get; set; }
[Column("source_id")]
public int SourceId { get; set; }
[Indexed]
[Column("type")]
public byte Type { get; set; }
[Column("rate")]
public int Rate { get; set; }
[Column("created_at")]
public string CreatedAt { get; set; }
[Column("updated_at")]
public string UpdatedAt { get; set; }
[NotMapped]
public Phrase Phrase { get; set; }
[NotMapped]
public Word Word { get; set; }
[NotMapped]
public Text Text { get; set; }
[NotMapped]
public IList<Translation> Translations { get; }
[NotMapped]
public string Content
{
get {
switch (Type)
{
case EntryType.Phrase:
return Phrase?.Content;
case EntryType.Word:
return Word?.Content;
case EntryType.Text:
return Text?.Content;
}
return "";
}
}
}
}
【问题讨论】:
-
我的建议:在
Result和await之间进行选择。使用其中之一,而不是两者都使用。否则……死锁。如果您决定使用后者,avoid async void. -
@TheodorZoulias 我简化了代码库,请检查您是否可以提供帮助,我认为这与 Realm 的工作方式更相关
-
现在没有
Result,因此可能出现死锁的主要嫌疑人已被消除。您得到的错误意味着存在线程关联。您可能会发现这个问题很有用:Forcing certain code to always run on the same thread.
标签: c# .net asynchronous async-await realm