(A)等待多个实例只触发一次事件



我有一个列表,这个SomeAttachmentClass有一个UploadCompleted事件,在调用. save()方法时,只引发一次。. save()方法在保存和上传实际完成之前不会阻塞,而是立即返回并通过所述事件发出完成信号。

现在我想要和需要做的基本上是等待列表<>中的所有实例(确切地)引发该事件一次,然后继续…,问题是,我怎样才能做到最简单/最优雅?

我正在考虑在每个实例上使用RX的FromEvent(…)与。take(1)相结合,在所有这些每个实例流上执行。selectmany()并等待…但我不确定是否有更好的方法。

这可以解决这个问题-感谢Shlomo作为起点。

void Main()
{
    Func<SomeAttachment, IObservable<object>> save = sa =>
        Observable.Create<object>(o =>
        {
            var ob =
                Observable
                    .FromEventPattern<object>(
                        eh => sa.UploadCompleted += eh,
                        eh => sa.UploadCompleted -= eh)
                    .Take(1)
                    .Select(x => x.EventArgs);
            var subscription = ob.Subscribe(o);
            sa.Save();
            return subscription;
        });
    var list = Enumerable.Range(0, 10).Select(i => new SomeAttachment(i)).ToList();
    list
        .ToObservable()
        .SelectMany(o => save(o))
        .ToArray()
        .Subscribe(_ => Console.WriteLine("All Complete. Handling logic goes here."));
}
public class SomeAttachment
{
    private static Random random = new Random();
    private readonly int _id;
    public SomeAttachment(int id)
    {
        _id = id;
    }
    public int Id
    {
        get { return _id; }
    }
    public async Task Save()
    {
        //await Task.Delay(TimeSpan.FromMilliseconds(random.Next(1000, 3000)));
        UploadCompleted?.Invoke(this, new object());
    }
    public event EventHandler<object> UploadCompleted;
}

这是一个Rx实现。你不需要等待,Rx会为你做的。注释掉的行用于在LinqPad中调试/运行:

void Main()
{
    var list = Enumerable.Range(0, 10).Select(i => new SomeAttachment(i)).ToList();
    list.ToObservable()
        .Do(sa => sa.Save())
        //.Do(sa => Console.WriteLine($"{sa.Id}: Save called"))
        .Select(sa => Observable.FromEventPattern<object>(eh => sa.UploadCompleted += eh, eh => sa.UploadCompleted -= eh))
        .SelectMany(o => o.Take(1))
        //.Do(o => Console.WriteLine($"{(o.Sender as SomeAttachment).Id}: Upload completed."))
        .All(_ => true)
        .Take(1)
        .Subscribe(_ => Console.WriteLine("All Complete. Handling logic goes here."));
}
// Define other methods and classes here
public class SomeAttachment
{
    private static Random random = new Random();
    private readonly int _id;
    public SomeAttachment(int id)
    {
        _id = id;
    }
    public int Id
    {
        get { return _id; }
    }
    public async Task Save()
    {
        await Task.Delay(TimeSpan.FromMilliseconds(random.Next(1000, 3000)));
        UploadCompleted?.Invoke(this, new object());
    }
    public event EventHandler<object> UploadCompleted;
}

相关内容

  • 没有找到相关文章

最新更新