与Observables的复杂流程

时间:2016-01-19 12:47:05

标签: c# .net wpf system.reactive observable

我有一系列图像(IObservable<ImageSource>)通过这个“管道”。

  1. 使用OCR识别每个图像
    • 如果结果具有有效值,则会将其上传到可在给定时间(而非并发)注册一组结果的服务。
    • 如果结果具有任何无效值,则会将其呈现给用户以进行修复。修复后,流程继续进行。
  2. 在此过程中,用户界面应保持响应。
  3. 问题在于,当用户必须进行交互时,我不知道如何处理这种情况。我就是不能这样做

            subscription = images                
                .Do(source => source.Freeze())
                .Select(image => OcrService.Recognize(image))                
                .Subscribe(ocrResults => Upload(ocrResults));
    

    ...因为当用户必须修复ocrResults时,应该保持流程直到接受有效值(即用户可以执行命令单击按钮)

    我怎么说:如果结果无效,请等到用户修复它们?

3 个答案:

答案 0 :(得分:2)

我假设您的UploadAsync方法返回Task以允许您等待它完成?如果是这样,有SelectMany的重载处理任务。

images.Select(originalImage => ImageOperations.Resize(originalImage))
    .SelectMany(resizedImg => imageUploader.UploadAsync(resizedImg))
    .Subscribe();

答案 1 :(得分:2)

假设您有一个实现“用户修复过程”的异步方法:

/tmp/

然后您的观察结果变为:

/* show the image to the user, which fixes it, returns true if fixed, false if should be skipped */
async Task UserFixesTheOcrResults(ocrResults);

答案 2 :(得分:2)

这似乎是UX,WPF和Rx的混合,都包含在一个问题中。试图用Rx解决它可能会让你进入尾部旋转。我相信你可以只用Rx解决它,而不再考虑它,但你想要吗?它是可测试的,松散耦合的并且易于维护吗?

在我对问题的理解中,你必须遵循以下步骤

  1. 用户上传/选择一些图片
  2. 系统对每个图像执行OCR
  3. 如果OCR工具认为图像源有效,则上传处理结果
  4. 如果OCR工具认为图像源无效,则用户&#34;修复&#34;结果和结果已上传
  5. 但这可能更好地描述为

    1. 用户上传/选择一些图片
    2. 系统对每个图像执行OCR
    3. OCR的结果放在验证队列中
    4. 虽然结果无效,但用户需要手动将其更新为有效状态。
    5. 上传了有效结果
    6. Sequence diagram

      所以这对我来说似乎需要基于任务/队列的UI,以便用户可以看到他们需要处理的无效OCR结果。这也告诉我,如果涉及一个人,它应该在Rx查询之外。

      步骤1 - 执行ORC

      subscription = images                
              .Subscribe(image=>
              {
                //image.Freeze() --probably should be done by the source sequence
                var result = _ocrService.Recognize(image);
                _validator.Enqueue(result);
              });
      

      第2步 - 验证结果

      //In the Enqueue method, if queue is empty, ProcessHead();
      //Else add to queue.
      //When Head item is updated, ProcessHead();
      //ProcessHead method checks if the head item is valid, and if it is uploads it and remove from queue. Once removed from queue, if(!IsEmpty) {ProcessHead();}
      
      
      //Display Head of the Queue (and probably queue depth) to user so they can interact with it.
      

      第3步 - 上传结果

      Upload(ocrResults)
      

      所以这里Rx只是我们军火库中的一个工具,而不是需要解决所有问题的锤子。我发现大多数&#34; Rx&#34;大小增加的问题,Rx只是各种Queue结构的入口和出口点。这允许我们在我们的系统中显式排队而不是隐式(即隐藏在Rx运算符内)。