static void NotifyJobDone(BitmapRequest req)
    {
      if (req.Handle.IsDisposed
        || req.Callback == null)
      {
        req.CleanUp();
        return;
      }

      req.Callback(req.CreateLoadingResult());
      req.CleanUp();
    }
    /// <summary>
    /// Generate STREAM and
    /// push it to bitmap loading observable
    /// </summary>
    /// <param name="req"></param>
    static void GenerateStreamAndPush(BitmapRequest req)
    {
      if (req.Handle.IsDisposed)
      {
        req.CleanUp();
        return;
      }

      if (string.IsNullOrEmpty(req.ResourcePath) == false)
      {
        var stminfo = Application.GetResourceStream(new Uri(req.ResourcePath, UriKind.Relative));
        if (null == stminfo
          || null == stminfo.Stream)
        {
          req.Stream = null;
          req.Succeeded = false;
          req.ErrorMessage = "Failed to get resource stream";

          _requestdoneob.OnNext(req);
          return;
        }

        req.Stream = MemoryStreamFromStream(stminfo.Stream);
        _streamob.OnNext(req);
        return;
      }

      if (string.IsNullOrEmpty(req.IsoPath) == false)
      {
        byte[] buf = StorageIo.ReadBinaryFile(req.IsoPath);
        if (null == buf)
        {
          Debug.WriteLine("Unable to read a file:{0}", req.IsoPath);
          req.Stream = null;
          req.Succeeded = false;
          req.ErrorMessage = "Unable to read file";

          _requestdoneob.OnNext(req);
          return;
        }
        req.Stream = new MemoryStream(buf);
        _streamob.OnNext(req);
        return;
      }

      //
      // Unrecharable.
      //
      Debug.Assert(false);
    }
    /// <summary>
    /// Generate bitmap image and start background loading
    /// </summary>
    /// <param name="req"></param>
    static void GenerateBackgroundBitmapLoadingAndPush(BitmapRequest req)
    {
      if (req.Handle.IsDisposed)
      {
        req.CleanUp();
        return;
      }

      var bmp = new BitmapImage
      {
        CreateOptions = BitmapCreateOptions.BackgroundCreation
      };

      var opensucceeded = Observable.FromEventPattern<RoutedEventArgs>(
            h => bmp.ImageOpened += h,
            h => bmp.ImageOpened -= h)
            .Select<EventPattern<RoutedEventArgs>, EventArgs>(x => x.EventArgs as EventArgs);
      var openfailed =
        Observable.FromEventPattern<ExceptionRoutedEventArgs>(
                          h => bmp.ImageFailed += h,
                          h => bmp.ImageFailed -= h)
                  .Select<EventPattern<ExceptionRoutedEventArgs>, EventArgs>(x => x.EventArgs as EventArgs);

      req.BmpLoadingSubscription =
        Observable.Amb(opensucceeded, openfailed)
                  .Do(x => Debug.WriteLine("bitmap loaded: Received request - {0}", req.IsoPath))
                  .Subscribe
                    (args =>
                      {
                        --_numprocessing;
                        if (req.Handle.IsDisposed)
                        {
                          req.CleanUp();
                          return;
                        }

                        if (args is ExceptionRoutedEventArgs)
                        {
                          req.Succeeded = false;
                          req.ErrorMessage = (args as ExceptionRoutedEventArgs).ErrorException.ToString();
                          _requestdoneob.OnNext(req);
                          return;
                        }

                        if (args is RoutedEventArgs)
                        {
                          req.Succeeded = true;
                          req.BmpWidth = req.Bmp.PixelWidth;
                          req.BmpHeight = req.Bmp.PixelHeight;
                          _requestdoneob.OnNext(req);
                          return;
                        }
                      }
                    );

      ++_numprocessing;
      req.Bmp = bmp;
      bmp.SetSource(req.Stream);
    }
    public static IDisposable LoadIsoBitmapAsync(
              string path,
      Action<LoadingResult> callback)
    {
      var req = new BitmapRequest
      {
        Id = Guid.NewGuid().ToString(),
        Handle = new BooleanDisposable(),
        IsoPath = path,
        Callback = callback
      };

      _requestob.OnNext(req);
      return req.Handle;
    }