0

I am trying to read the contents of a directory that has over 100k+ files. Each file will be parsed eventually. Since this is a long time consuming task I want to provide feedback to the end user that the program has not "frozen", This is an MVP pattern project setup.

I am using async Task and IProgress to provide feedback to the UI, but either methods below lock up the UI and I can't figure out why..

    private async void MainFormViewOnStartProcessingFiles(object sender, EventArgs eventArgs)
    {
        // The Progress<T> constructor captures our UI context,
        //  so the lambda will be run on the UI thread.
        var asyncProgress = new Progress<int>(percent =>
        {
            EventAggregator.Instance.Publish(new DisplayMainFormWaitBarMessage($"Async found {percent} files..."));
        });

        // GetDirectoryFiles is run in the thread pool
        await Task.Run(() => GetDirectoryFilesAsync(asyncProgress));


        var syncProgress = new Progress<int>(percent =>
        {
            EventAggregator.Instance.Publish(new DisplayMainFormWaitBarMessage($"Sync found {percent} files..."));
        });

        GetDirectoryFiles(syncProgress);

    }

This updates the UI

        private void DisplayWaitingBarMessage(DisplayMainFormWaitBarMessage obj)
    {
        _mainFormView.DisplayWaitBarMessage(obj.DisplayText);
    }

This is my Async and Non Async code to read the files into a queue

        private async Task GetDirectoryFilesAsync(IProgress<int> taskProgress)
    {
        await Task.Run(() =>
        {
            try
            {
                var directoryPath = Directory.GetCurrentDirectory() + @"\..\..\..\FUG_2017\";
                var _listOfDirectoryFiles = Directory.GetFiles(directoryPath).Take(100);

                var fileCount = 0;
                foreach (var filePath in _listOfDirectoryFiles)
                {
                    _filesToProcessQueue.Enqueue(filePath);
                    fileCount++;

                    taskProgress?.Report(fileCount);
                }
            }
            catch (Exception exc)
            {
                FlushAndExit(exc);
            }
        });
    }

    private void GetDirectoryFiles(IProgress<int> taskProgress)
    {
        try
        {
            var directoryPath = Directory.GetCurrentDirectory() + @"\..\..\..\FUG_2017\";
            EventAggregator.Instance.Publish(new DisplayMainFormWaitBarWithMessage(ElementVisibility.Visible, $"Inspecting path {directoryPath}"));

            var _listOfDirectoryFiles = Directory.GetFiles(directoryPath).Take(1000);

            var fileCount = 0;
            foreach (var filePath in _listOfDirectoryFiles)
            {
                _filesToProcessQueue.Enqueue(filePath);
                fileCount++;

                EventAggregator.Instance.Publish(new DisplayMainFormWaitBarWithMessage(ElementVisibility.Visible, $"Loaded file {fileCount} of {_listOfDirectoryFiles.Count()} to Queue..."));
                taskProgress?.Report(fileCount);
            }

            EventAggregator.Instance.Publish(new DisplayMainFormWaitBarWithMessage(ElementVisibility.Visible, $"Loaded {_listOfDirectoryFiles.Count()} files to Queue..."));
        }
        catch (Exception exc)
        {
            FlushAndExit(exc);
        }
    }
Geovani Martinez
  • 2,053
  • 2
  • 27
  • 32
  • 1
    Pause the debugger when it's hung & look at the call stack. – SLaks Dec 01 '17 at 15:32
  • 1
    Multiple nested `Task.Run()` calls mean that you're likely to end up with `Task`s that return `Task`s (and the lifecycle of the outer `Task` is likely shorter than that of the inner `Task`. I'd generally *avoid* code that mixes both `Task.Run()` and `async`/`await` since it's easy to get tangled up in the nesting. – Damien_The_Unbeliever Dec 01 '17 at 15:38
  • You can at least tell us on which line it hangs. – Evk Dec 01 '17 at 15:46
  • The program does not "hang", it's the UI that is not refreshing after each status update, triggering the feeling that the program is stuck. My logger logs each file entry correctly. – Geovani Martinez Dec 01 '17 at 15:55
  • Replace `await Task.Run(() => GetDirectoryFilesAsync(asyncProgress));` with `await GetDirectoryFilesAsync(asyncProgress)` and see if that helps. – Evk Dec 01 '17 at 16:00
  • @Evk I did as you said and the program executes, no improvement on the UI responsiveness but it appears to be a code quality improvement (No Task nesting) – Geovani Martinez Dec 01 '17 at 17:17

0 Answers0