简短版本:如何在自己的代码(https://github.com/akavache/Akavache/blob/501b397d8c071366c3b6783aae3e98695b3d7442/src/Akavache/Portable/JsonSerializationMixin.cs#L202)中实现像Akavache一样的GetAndFetchLatest方法-而不添加Akavache?

长版:
我有一个从磁盘返回T列表的方法,我有一个从HTTP服务返回相同类型List<T>的方法。
两者都包装为Task<List<T>>异步

在我的视图模型中,我只想调用1个返回Observable<List<T>>的方法。

因此,在ViewModel中,我使用.Subscribe()方法来更新UI。
本质上,需要两次通知我数据可用,并且订阅中的代码也将进行两次。

Akavache可以使用GetAndFetchLatest方法的形式使用此功能...但是我对RX的理解还不够流利,无法理解如何使用2个数据方法调用自己实现此功能。

注意:所以我不想等待这两个任务!我想同时触发它们,并在它们返回数据时立即触发Observable

有小费吗?

最佳答案

给定Task<List<T>> GetFromWeb()Task<List<T>> GetFromDisk(),简单的答案是这样的:

var merged = Observable.Merge(
    GetFromWeb().ToObservable(),
    GetFromDisk().ToObservable()
);

//Same thing using extension syntax
var simply = GetFromWeb().ToObservable()
    .Merge(GetFromDisk().ToObservable());


但是,这不能解决GetFromWebGetFromDisk之前完成的不太可能但可能的情况,在这种情况下,我假设您想忽略GetFromDisk的结果。为了解决这个问题,您将需要一些体操:

public IObservable<T> Prioritize<T>(params IObservable<T>[] orderedByDescendingPriority)
{
    return orderedByDescendingPriority
        .Select((o, i) => o.Select(item => Tuple.Create(orderedByDescendingPriority.Length - i, item)))
        .Merge()
        .Select(t => new Func<Tuple<int, T, bool>, Tuple<int, T, bool>>(t2 => Tuple.Create(Math.Max(t2.Item1, t.Item1), t.Item2, t.Item1 >= t2.Item1)))
        .Scan(Tuple.Create(0, default(T), false), (t, f) => f(t))
        .Where(t => t.Item3)
        .Select(t => t.Item2);
}

var merged = Prioritize(
    GetFromWeb().ToObservable(),
    GetFromDisk().ToObservable()
);




编辑:

如果您总是希望GetFromDisk总是显示在GetFromWeb之前,那么这是一个简单的Concat操作。之所以可行,是因为.NET任务在您引用其功能后即自动启动:

    var t1 = GetFromDisk();
    var t2 = GetFromWeb();

    var merged = Observable.Concat(
        t1.ToObservable(),
        t2.ToObservable()
    );

关于c# - 尽快合并请求并产生结果,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44133100/

10-11 15:52