我剛纔注意到await
關鍵字可以使用的Rx可觀察使用,例如:爲什麼可能等待Rx可觀察?
await Observable.Interval(TimeSpan.FromHours(1));
我敢肯定,它只能在配合使用的任務。
那是什麼使它成爲可能?觀察對象的知識是否被硬編碼到編譯器中?
我剛纔注意到await
關鍵字可以使用的Rx可觀察使用,例如:爲什麼可能等待Rx可觀察?
await Observable.Interval(TimeSpan.FromHours(1));
我敢肯定,它只能在配合使用的任務。
那是什麼使它成爲可能?觀察對象的知識是否被硬編碼到編譯器中?
不,編譯器沒有IObservable<T>
的專門知識。根據C#5規範的第7.7.7.1節,如果對象具有方法,或者存在名爲GetAwaiter
的擴展方法,該擴展方法返回實現System.Runtime.CompilerServices.INotifyCompletion
的類型,則可等待它。參見Steven Toub的文章Await anything。
更具體地,從該規範
一個AWAIT表達的任務需要爲awaitable。表達噸是awaitable如果下列之一成立:
- 噸是編譯時類型動態的
- 噸具有稱爲GetAwaiter與沒有參數和類型參數可訪問的實例或擴展方法,以及以下所有的返回類型A:
1. A實現接口System.Runtime.CompilerServices.INotifyCompletion(以下簡稱爲INotifyCompletion)
2. A具有可訪問的可讀實例屬性IsCompleted類型bool
3.有沒有參的可訪問實例方法調用getResult並沒有類型參數
注意如何,這是類似於如何foreach
不需要IEnumerable<T>
而只是一個返回兼容對象GetEnumerator方法。這種鴨子輸入是一種性能優化,它允許編譯器在沒有裝箱的情況下使用值類型。這可以用來避免性能敏感的代碼中不必要的分配。
我認爲這是因爲System.Reactive.Linq
在IObservable
上定義了一個GetAwaiter
擴展方法。正如@mike z解釋的那樣,允許您等待IObservable
。下面是方法:
public static AsyncSubject<TSource> GetAwaiter<TSource>(this IObservable<TSource> source)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
return s_impl.GetAwaiter<TSource>(source);
}
返回類型AsyncSubject<T>
實現INotifyCompletion
並具有IsCompleted
財產和GetResult
方法。
public sealed class AsyncSubject<T> : ISubject<T>, ISubject<T, T>, IObserver<T>, IObservable<T>, IDisposable, INotifyCompletion
{
// Fields
private Exception _exception;
private readonly object _gate;
private bool _hasValue;
private bool _isDisposed;
private bool _isStopped;
private ImmutableList<IObserver<T>> _observers;
private T _value;
// Methods
public AsyncSubject();
private void CheckDisposed();
public void Dispose();
public AsyncSubject<T> GetAwaiter();
public T GetResult();
public void OnCompleted();
public void OnCompleted(Action continuation);
private void OnCompleted(Action continuation, bool originalContext);
public void OnError(Exception error);
public void OnNext(T value);
public IDisposable Subscribe(IObserver<T> observer);
// Properties
public bool HasObservers { get; }
public bool IsCompleted { get; }
值得注意的是,當調用'OnCompleted'時,等待observable只返回最後一個值。如果序列中沒有任何值,則會拋出異常。 – 2014-12-11 04:07:24