ScheduledDisposable.cs 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
  2. using System.Reactive.Concurrency;
  3. using System.Threading;
  4. namespace System.Reactive.Disposables
  5. {
  6. /// <summary>
  7. /// Represents a disposable resource whose disposal invocation will be scheduled on the specified <seealso cref="T:System.Reactive.Concurrency.IScheduler"/>.
  8. /// </summary>
  9. public sealed class ScheduledDisposable : ICancelable
  10. {
  11. private readonly IScheduler _scheduler;
  12. private volatile IDisposable _disposable;
  13. /// <summary>
  14. /// Initializes a new instance of the <see cref="T:System.Reactive.Disposables.ScheduledDisposable"/> class that uses an <see cref="T:System.Reactive.Concurrency.IScheduler"/> on which to dispose the disposable.
  15. /// </summary>
  16. /// <param name="scheduler">Scheduler where the disposable resource will be disposed on.</param>
  17. /// <param name="disposable">Disposable resource to dispose on the given scheduler.</param>
  18. /// <exception cref="ArgumentNullException"><paramref name="scheduler"/> or <paramref name="disposable"/> is null.</exception>
  19. public ScheduledDisposable(IScheduler scheduler, IDisposable disposable)
  20. {
  21. if (scheduler == null)
  22. throw new ArgumentNullException("scheduler");
  23. if (disposable == null)
  24. throw new ArgumentNullException("disposable");
  25. _scheduler = scheduler;
  26. _disposable = disposable;
  27. }
  28. /// <summary>
  29. /// Gets the scheduler where the disposable resource will be disposed on.
  30. /// </summary>
  31. public IScheduler Scheduler
  32. {
  33. get { return _scheduler; }
  34. }
  35. /// <summary>
  36. /// Gets the underlying disposable. After disposal, the result is undefined.
  37. /// </summary>
  38. public IDisposable Disposable
  39. {
  40. get
  41. {
  42. var current = _disposable;
  43. if (current == BooleanDisposable.True)
  44. return DefaultDisposable.Instance; // Don't leak the sentinel value.
  45. return current;
  46. }
  47. }
  48. /// <summary>
  49. /// Gets a value that indicates whether the object is disposed.
  50. /// </summary>
  51. public bool IsDisposed
  52. {
  53. get { return _disposable == BooleanDisposable.True; }
  54. }
  55. /// <summary>
  56. /// Disposes the wrapped disposable on the provided scheduler.
  57. /// </summary>
  58. public void Dispose()
  59. {
  60. Scheduler.Schedule(DisposeInner);
  61. }
  62. private void DisposeInner()
  63. {
  64. #pragma warning disable 0420
  65. var disposable = Interlocked.Exchange(ref _disposable, BooleanDisposable.True);
  66. #pragma warning restore 0420
  67. if (disposable != BooleanDisposable.True)
  68. {
  69. disposable.Dispose();
  70. }
  71. }
  72. }
  73. }