【问题标题】:OrderBy an list in a task function asyncOrderBy 任务函数异步中的列表
【发布时间】:2018-11-29 00:26:42
【问题描述】:

好的,我正在与奥尔良合作,我真正想做的就是在状态值之后对列表进行排序。我尝试这样做

public async Task SortEntries()
    {
         State.Entries.OrderBy(GetComparator);
    }

    private async decimal GetComparator(IEntryGrain x)
    {
        var a = await x.GetState();

        return Task.FromResult(a);
    }

但这有两个错误,我正在努力解决。 Task SortEntries 任务中的第一个任务缺少等待运算符,我猜它可能仍然有效,问题是 GetComparator 说异步方法必须是 void、Task 或 Task。我首先想到的最简洁的方法是在 SortEntries 中进行所有排序,例如这个

State.Entries.OrderBy((x) => x.GetState().Result.TotalPoints);

但是 GetState() 需要与等待异步,但我不能在 orderBy 或 sort 上这样做。任何可以将我推向正确方向或遇到类似情况的人

【问题讨论】:

    标签: c# asynchronous orleans


    【解决方案1】:

    1.) OrderBy 不适用于异步/等待。一个快速的解决方法是在 GetComparator 中使用 GetState 的 Result 属性

    private decimal GetComparator(IEntryGrain x)
    {
        var task = x.GetState();
        task.Wait();
    
        if(task.IsFaulted)
            throw new Exception($"could not get the state: {task.Exception}", task.Exception);
    
        return task.Result;
    }
    

    2.) OrderBy 只返回一个IEnumerable,因此不会在那里订购。需要枚举一次才能执行订单。而且你需要返回结果,因为OrderBy 只返回一个有序列表,而不是对列表本身进行排序。

    public IList<IEntryGrain> SortEntries()
    {
         return State.Entries.OrderBy(GetComparator)
                             .ToList();
    }
    

    如果它是可写且线程安全的,则将其写回属性

    public void SortEntries()
    {
         State.Entries = State.Entries.OrderBy(GetComparator)
                                      .ToList();
    }
    

    所以你得到:

    public IList<IEntryGrain> SortEntries()
    {
        return State.Entries.OrderBy(GetComparator)
                            .ToList();
    }
    
    private decimal GetComparator(IEntryGrain x)
    {
        var task = x.GetState();
        task.Wait();
    
        if(task.IsFaulted)
            throw new Exception($"could not get the state: {task.Exception}", task.Exception);
    
        return task.Result;
    }
    

    【讨论】:

    • State.Entries.OrderBy(async (x) =&gt; await GetComparator(x));State.Entries.OrderBy(GetComparator); 的行为相同,除了您的版本分配更多对象并花费更多时间这一事实。除了性能下降之外,两者之间没有明显的差异。此外,您的第二个和最后一个方法根本不会编译,因为您返回的类型是编译器不希望为这些方法返回的类型。
    • 现在你只是同步阻塞异步操作,这只会死锁,而不是异步完成工作,这就是首先在这里进行异步操作的全部意义。
    • 它将杀死奥尔良调度程序,永远不要在奥尔良使用阻塞调用!我宁愿重新考虑整个问题。您真的想在每次排序期间为每次比较调用另一个谷物吗?即使没有阻塞调用,它也会破坏性能:条目颗粒将从数据库加载到内存中,通常在其他节点等。如果条目是对颗粒的一些引用,缓存用于比较的值。但是你真的需要为条目提供谷物吗?还是只是 POCO?条目是 DDD/聚合根吗?
    • 将异步方法转换为同步是一个坏主意,正如@Servy 所建议的那样,您应该只使用普通异步
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-09
    • 1970-01-01
    • 2014-07-24
    • 1970-01-01
    • 2014-01-21
    相关资源
    最近更新 更多