Search code examples
c#asynchronousorleans

OrderBy an list in a task function async


Okay i am working with orleans and all i really want to do is sort an list after a value in state. i try to this by doing this

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

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

        return Task.FromResult(a);
    }

but this got two wrongs in them that i am trying to solve. first of the Task SortEntries task lacks an await operator which i guess might still work the problem is that GetComparator says an async method must be void, Task or Task.The most neat way i first thought would be to do all the sorting in SortEntries like this

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

But the GetState() need to be async with an await but i cant do that on the orderBy or sort. Anyone who can push me in the right direction or encountered something similar


Solution

  • 1.) OrderBy doesn't work with async/await. A qiuck fix would be to use the Result property of GetState in GetComparator

    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 return only an IEnumerable, so it wont be ordered there. Need to enumerate it once to execute the order by. And you need to return the result because OrderBy only returns a ordered list, but does not order the list itself.

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

    or write it back to the property if it is writable and thread safe

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

    So you get:

    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;
    }