C# 任务中的领域异步使用

C# 任务中的领域异步使用,c#,xamarin,realm,C#,Xamarin,Realm,我试图更好地理解如何在异步场景中使用领域。据我所知,领域实例只能访问它创建的线程上的对象。因此,要执行异步事务,我需要使用GetInstance(“SomeRealmFile”)创建一个新的领域实例 有一个名为Task WriteAsync(Action-Action)的函数,它可以在工作线程(后台)上执行写事务 下面是一个示例场景。应用程序需要发出web请求。因此,它运行一个异步任务函数去web上获取一些数据。请求成功返回,现在应用程序希望将该数据解析到一个领域对象中,并使用Realm.Man

我试图更好地理解如何在异步场景中使用领域。据我所知,领域实例只能访问它创建的线程上的对象。因此,要执行异步事务,我需要使用
GetInstance(“SomeRealmFile”)创建一个新的领域实例

有一个名为
Task WriteAsync(Action-Action)
的函数,它可以在工作线程(后台)上执行写事务

下面是一个示例场景。应用程序需要发出web请求。因此,它运行一个异步任务函数去web上获取一些数据。请求成功返回,现在应用程序希望将该数据解析到一个领域对象中,并使用
Realm.Manage(T Obj)
将其持久化到数据库中。请注意,整个场景假设我们已经在UI主线程上创建了领域数据库

让我们假设此时我们希望留在后台线程上,在启动web请求的异步任务函数的上下文中

现在我们的情况是,我们通过
var results=await WebFetch()获得web请求(数据)的结果,可能改为使用类似TaskCompletionSource的东西,然后最后我们可以在工作线程上执行领域写事务。
我假设要在此时调用异步写事务,我们需要获取领域的一个新实例,并将其传递给
WriteAsync()
函数

这引发了另一个问题,让我们假设在数据库编写事务之前,我们希望在编写东西之前进行一些查询和检查。如果我们在异步函数中执行这些查询,会发生什么?因为我以前尝试过很多奇怪的事情,有时候它可以工作,有时候查询只返回null(当然取决于查询的类型)。在主线程上完美工作的查询

编辑这可能是一个bug,异步函数中的查询非常不可靠

因此,为了清楚起见,我们仍然假设我们以前从异步任务(web fetch)返回,现在我们正在执行一些领域查询,然后调用
任务WriteAsync(Action Action)
函数将数据写入数据库。这是正确的方法吗?在这一点上搞清楚就好了

最后一点,异步写事务是必要的吗?什么样的领域场景(写事务)可能会阻止UI线程足够长的时间,以至于它需要并证明可以在工作线程上执行(仅从移动开发的角度来看)

Edit下面链接的异步示例回答了这个问题,即任何占用大量cpu资源的进程。所以我们假设基本的领域写事务,例如管理50个对象的列表不需要是异步的

一个伪代码示例会很棒

编辑 在我的头顶上添加了一个代码示例

async Task RealmWritesAsync
{
    var result = await WebFetch();

    // Maybe do some queries here
    var realm = Realm.GetInstance("RealmFile");
    await realm.WriteAsync(realm =>
    {
          // Realm.Manage the results
    });
}

Environment=Xamarin.iOS/Droid使用MvvmCross的PCL项目

我最近在自己的应用程序中遇到了这个问题,但从未在StackOverflow上找到好的答案,因此我将分享我学到的知识

Realm
类上的
WriteAsync
函数仅适用于需要在写事务中执行大量CPU繁重工作的情况。传递给lambda的
Realm
实例是工作线程上的一个实例,对于在lambda内执行的操作,必须使用该实例而不是原始
Realm
实例

如果您只想在不一定占用CPU的写事务中执行异步工作,则必须手动启动事务,然后在完成后提交它。我编写了一个扩展方法来简化这个过程,名为
WriteTask
,以避免与现有的
WriteAsync
函数发生冲突:

//
///Realm.Write的异步友好版本,这意味着work函数可以返回任务
///这将在交易范围内等待。
/// 
公共静态异步任务WriteTask(此领域,Func workFunction)
{
使用var transaction=realm.BeginWrite();
等待工作函数();
Commit();
}
注意,这使用了使用声明语法的C#8.0。如果不能使用C#8.0,只需将其替换为using块:

使用(var transaction=realm.BeginWrite())
{
等待工作函数();
Commit();
}

只要从主(UI)线程调用
.WriteTask
方法,并且在lambda中等待任何
任务时不使用
.ConfigureAwait(false)
,这将允许在写事务中完成异步工作,而不需要单独的
领域
实例。但是,请注意不要让多个并发异步操作同时尝试启动事务,因为这会引发异常。

我最近在自己的应用程序中遇到了这种情况,但从未找到有关StackOverflow的好答案,因此我将与大家分享我学到的知识

Realm
类上的
WriteAsync
函数仅适用于需要在写事务中执行大量CPU繁重工作的情况。传递给lambda的
Realm
实例是工作线程上的一个实例,对于在lambda内执行的操作,必须使用该实例而不是原始
Realm
实例

如果您只想在不一定占用CPU的写事务中执行异步工作,则必须手动启动事务,然后在完成后提交它。我编写了一个扩展方法来简化这个过程,名为
WriteTask
,以避免与现有的
WriteAsync
函数发生冲突:

//
///Realm.Write的异步友好版本,这意味着work函数可以返回任务
///这将在交易范围内等待。
/// 
公共静态异步任务WriteTask(此域)