如何在没有阻塞调用的情况下从 IObservable 订阅中获取结果?

How to get the result from IObservable subscription without a blocking call?

我正在尝试使用 ListObjectsAsync 方法在我的 MinIO 服务器的存储桶中获取文件名。

相关代码如下:

public async Task<string> GetFileName(string userID, string datasetID) 
{
    ListObjectsArgs args = new ListObjectsArgs()
        .WithBucket(userID)
        .WithPrefix(datasetID)
        .WithRecursive(true);

    var files = _minio.ListObjectsAsync(args);

    List<string> fileNames = new();
    
    IDisposable subscription = files
        .Subscribe(item => 
            fileNames.Add(item.Key),
            () => Console.WriteLine(fileNames.Count)
        );
      
    // I want to return one of the filenames here!
    return ""; 
}

上面的代码按预期填充了列表 fileNames,并在相应位置打印出正确数量的文件。但是,我想在上面的函数中使用数据。 我知道我可以做到以下几点:

files.ToList().Wait(); 

但是,这是一个阻塞调用。我应该简单地将此调用包装到 Task 中还是有其他(更好的)方法来获取所需的数据?

而不是订阅,return files.ToTask()

编辑

正如您在评论中提到的,首先使用 .ToList() 以便将所有接下来的事件聚集到一个事件中。如果你正在寻找一个特定的文件,就像另一个答案暗示的那样,那么使用 .Filter.

此外,我认为您的 return 类型应该是一个包含字符串数组而不是单个字符串的任务...(除非您只想要一个文件并过滤掉所有其他文件。)

我觉得你可以一个一个地检查你收到的文件,当当前文件满足特定条件时停止处理其余的文件。喜欢:

CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;
Item file = null;
files.Subscribe(
        item => {
            if (item.Key=="MyFile")
            {
                file=item; 
                source.Cancel();
            }
        },
        () => Console.WriteLine(fileNames.Count),
        token );