2014-10-07 4 views
2

Это не реальный пример жизни (и этот код, вероятно, не компилируется), но я пытаюсь сделать его немного проще, чем проблема, на самом деле у меня есть.Реактивные расширения: Zip-оператор, но другой

Скажем, у меня есть коллекция изображений:

private void IEnumerable<Image> GetImages() 
{ 
    foreach (var filename in GetFilenames()) 
    { 
     yield return Image.LoadFile(filename); 
    } 
} 

, и я хотел бы показать слайд-шоу, приводимый пользователем, нажав «пространство»:

var images = Observable.FromEvent(form, "KeyPress") 
    .Where(e => e.KeyCode == KeyCode.Space) 
    .Zip(GetImages.ToObservable(), (k, i) => i); 

И этот вид работ. Он выделяет следующее изображение при нажатии пробела. Проблема в том, что он фактически загружает их на полной скорости, поэтому они получают буферизацию и потребляют много памяти (и вычислительную мощность при загрузке). Я мог бы подавать отфильтрованные нажатия клавиш в GetImages и на zipping там, но я бы не сохранил чистоту GetImages.

Есть ли способ предотвратить перечислимое перечисление.ToObservable() из списка, если это необходимо?

Другой пример (это один компилируется):

var observable = 
    Observable.Interval(TimeSpan.FromSeconds(1)) 
    .Zip(
     Observable.Range(0, 1000000).Do(x => Console.WriteLine("produced {0}", x)), 
     (_, v) => v 
    ); 

var subscription = observable.Subscribe(x => Console.WriteLine("consumed {0}", x)); 

Console.WriteLine("Press <enter>..."); 
Console.ReadLine(); 

Он будет генерировать много «производства» (заранее), но только один «потребляется» в секунду.

ответ

5

идея Дейва прилипания к тянущих изображений из IEnumerable<T> является твердой, но вы можете достичь той же цели гораздо проще - просто удалить ToObservable() из кода:

var images = Observable.FromEvent(form, "KeyPress") 
         .Where(e => e.KeyCode == KeyCode.Space) 
         .Zip(GetImages() /* No ToObservable() here! */, (k, i) => i); 

Эта перегрузка Zip будет диск, перечислимый при нажатии клавиш.

+1

+1. Я просто пропустил одно ясное высказывание: наблюдаемый. Zip (перечислимый) - это предоставление перечислимого в темпе наблюдаемого (вы можете подразумевать этот ответ, но это явно не сказано). –

+0

+1 Еще одна «скрытая» перегрузка в Rx, и я никогда раньше не использовал ее. Должен был проверить список перегрузок перед публикацией - ошибка новичка ;-) –

+0

Как говорится - я был там, сделал это. Несомненно, скоро приедет в гости. :) –

0

Как насчет вытаскивания из перечислителя?

var keys = Observable.FromEventPattern<KeyPressEventArgs>(form, "KeyPress"); 
var slides = (from key in keys 
       where key.EventArgs.KeyCode == KeyCode.Space 
       select key) 
      .Publish(spaces => 
       { 
       var images = GetImages().GetEnumerator(); 

       return spaces.TakeUntil(from _ in spaces 
             where !images.MoveNext() 
             select Unit.Default) 
          .Select(_ => images.Current); 
       });