Timothy Ayodele
Timothy Ayodele

Reputation: 305

Calling IAsyncEnumerable<string> before other methods

Good day guys, Please I'm trying to read all file paths in a folder using IAsyncEnumerable, based on a library that I'm using. I've been able to create a method for that, but the challenge I have is that, the library method

StartQueryingFromFiles(IAsyncEnumerable<string> files, CancellationToken token) 

is called first, before calling the IAsyncEnumerable. Hence the values are always null.

What can I do to ensure that my parameter is not null. Please check my code below:

    private void btnStarts_Click(object sender, EventArgs e, Label searchLabel, TabPage page, ProgressBar bar)
    {
        try
        {
            bar.Style = ProgressBarStyle.Marquee;
            var searchPath = searchLabel.Text; //Path to folder
            var tokenSource = new CancellationTokenSource();
            var bolFinished = false;

            if (!string.IsNullOrEmpty(searchPath) && Directory.Exists(searchPath))
            {
                Task.Run(() =>
                {   
                    //The method below gets called first before the iteration                     
                    StartQueryingFromFiles(FetchAllItems(searchPath), tokenSource.Token);
                    bolFinished = true;
                });
            }
            else
            {
                MessageBox.Show("No Audio Files Found.");
            }

            if(bolFinished)
                bar.Style = ProgressBarStyle.Blocks;
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    //This gets called first, its supposed to return all files, but returns nothing
    IAsyncEnumerable<string> FetchAllItems(string searchPath)
    {
        return FetchItems(searchPath);
    }

    //This is called last, I don't know why. It reads the file paths in the folder
    async IAsyncEnumerable<string> FetchItems(string searchPath)
    {
        foreach (var item in Directory.EnumerateFiles(searchPath))
        {
            await Task.Delay(100);
            System.Diagnostics.Debug.WriteLine($"{DateTime.Now.ToLongTimeString()} Reading: {item}");
            yield return item;
        }
    }

Edit: Added the StartQueryingFromFiles method

    public void StartQueryingFromFiles(IAsyncEnumerable<string> files, CancellationToken token)
    {
        _ = QueryCommandBuilder.Instance
            .BuildRealtimeQueryCommand()
            .From(files, MediaType.Audio)
            .WithRealtimeQueryConfig(config =>
            {
        // provide a success callback that will be invoked for matches that pass result entry filter
        config.SuccessCallback = result =>
                {
                    foreach (var entry in result.ResultEntries)
                    {
                        System.Diagnostics.Debug.WriteLine($"Successfully matched {entry.TrackId}");
                    }
                };

        // configure result entry filter
        config.ResultEntryFilter = new TrackMatchLengthEntryFilter(5d);
                return config;
            })
            .UsingServices(modelService, mediaService)
            .Query(token);
    }

You can get more information about the library here: https://github.com/AddictedCS/soundfingerprinting/wiki/Realtime-Query-Command#query-from-a-continuous-stream-of-files

Thanks

Upvotes: 2

Views: 247

Answers (1)

Timothy Ayodele
Timothy Ayodele

Reputation: 305

Ok so after a lot of researching, kudos to this guys : https://www.dotnetcurry.com/csharp/async-streams

I was able to see that I could use System.Linq.Async to get my files to be converted to IAsyncEnumerable.

Hence instead of writting all those FetchItems methods above, no need. All I needed was do the below:

Task.Run(() =>
{
     DirectoryInfo di = new DirectoryInfo(searchPath);
     var getAllFiles = di.GetFiles()
           .Where(file => file.Name.EndsWith(".mp3"))
           .Select(file => file.Name).ToAsyncEnumerable<string>();

      StartQueryingFromFiles(getAllFiles, tokenSource.Token);
      bolFinished = true;
  });

Hence being able to get all the files into one IAsyncEnumerable.

Upvotes: 1

Related Questions