Click here to Skip to main content
15,904,023 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi all,

since VB wasn't an option to choose, I hope I'm still welcome here.

I've been trying to read a large number of particular entries from text files asynchroniously. Basically I'm now following the basic pattern from this Microsoft example.

Something seems to be wrong with my task creation: While, when debugging, 'entriesTasks' shows 53 tasks in the list right before entering the While-Loop, the loop is exited after the first line ('Dim finishedTask...') and 3 Threads end with Code 0.

Could someone please have a quick look on potential errors and guide me a bit with this? Just to mention it: The custom objects and methods should be ok (tested before) and the custom method, which is supposed to return 'Task(Of IEnumerable(Of FileData))', isn't even called i.e. a breakpoint not reached.

Thank you,
Michael

What I have tried:

VB
Dim entriesTasksQuery = From fi In LTODateilisten Select New Task(Of IEnumerable(Of FileData))(Function()
                                    Dim dlf As New DirListFile(fi)
                                    Return dlf.ReadFileEntriesAsync(fi)
                                  End Function)
Dim entriesTasks As List(Of Task(Of IEnumerable(Of FileData))) = entriesTasksQuery.ToList

While entriesTasks.Count > 0
     Dim finishedTask As Task(Of IEnumerable(Of FileData)) = Await Task.WhenAny(entriesTasks)
     entriesTasks.Remove(finishedTask)
     Dim entries As IEnumerable(Of FileData) = Await finishedTask
     Dim msg As String = $"{entries.Count} entries found."
     Debug.WriteLine(msg)
End While
Posted
Updated 23-Jul-23 5:27am
v3

1 solution

Quote:
Something seems to be wrong

This is like saying "My car won't start". We're like "did he turn the key, what happened?". You need to be specific.

When you ran the code did you get a thread exception error? That would be my first guess as you're doing unsafe thread operations. List is not thread- safe and entriesTasks.Remove(finishedTask) will be the culprit. You are better off using a ConcurrentBag and use TryTake to remove entries.

A rewrite would be:
VB
Dim entriesTasksQuery = From fi In LTODateilisten Select New Task(Of IEnumerable(Of FileData))(Function()
                                    Dim dlf As New DirListFile(fi)
                                    Return dlf.ReadFileEntriesAsync(fi)
                                  End Function)

Dim entriesTasks As New ConcurrentBag(Of Task(Of IEnumerable(Of FileData)))(entriesTasksQuery)

While entriesTasks.Count > 0
    Dim finishedTask As Task(Of IEnumerable(Of FileData)) = Await Task.WhenAny(entriesTasks)
    entriesTasks.TryTake(finishedTask)
    Dim entries As IEnumerable(Of FileData) = Await finishedTask
    Dim msg As String = $"{entries.Count} entries found."
    Debug.WriteLine(msg)
End While

This is untested but will fix the thread exception. But without you explaining in more detail, I am only guessing.

UPDATE

To force break on exceptions, go Debug > Windows > Exception Settings > click on "Common Language Runtime Exceptions" (must be a tick). This should catch it.

Update
Just did a quick sample and this works fine:
VB.NET
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Threading.Tasks

Module Program
    Sub Main()
        Dim Tasks As New List(Of Task)()
        For i As Integer = 0 To 99
            Dim task As New DummyTask()
            Tasks.Add(task.ExecuteAsync())
        Next

        Console.WriteLine($"Running Tasks: {Tasks.Count}")

        While Tasks.Count > 0
            Dim completed As List(Of Task) = Tasks.Where(Function(task) task.IsCompleted).ToList()
            If completed.Any() = True Then
                For Each task As Task In completed.ToList()
                    'Console.WriteLine($"ID: {task.Id} is {task.Status}")
                    Tasks.Remove(task)
                    Console.WriteLine($"Running Tasks: {Tasks.Count}")
                Next
            End If
        End While

        Console.ReadLine()
    End Sub
End Module

Public Class DummyTask
    Private random As New Random()

    Public Async Function ExecuteAsync() As Task
        Await Task.Delay(random.Next(3000, 5000))
    End Function
End Class

and the output:
Running Tasks: 100
Running Tasks: 99
Running Tasks: 98
Running Tasks: 97
Running Tasks: 96
Running Tasks: 95
Running Tasks: 94
Running Tasks: 93
Running Tasks: 92
Running Tasks: 91
Running Tasks: 90
Running Tasks: 89
Running Tasks: 88
Running Tasks: 87
Running Tasks: 86
Running Tasks: 85
Running Tasks: 84
Running Tasks: 83
Running Tasks: 82
Running Tasks: 81
Running Tasks: 80
Running Tasks: 79
Running Tasks: 78
Running Tasks: 77
Running Tasks: 76
Running Tasks: 75
Running Tasks: 74
Running Tasks: 73
Running Tasks: 72
Running Tasks: 71
Running Tasks: 70
Running Tasks: 69
Running Tasks: 68
Running Tasks: 67
Running Tasks: 66
Running Tasks: 65
Running Tasks: 64
Running Tasks: 63
Running Tasks: 62
Running Tasks: 61
Running Tasks: 60
Running Tasks: 59
Running Tasks: 58
Running Tasks: 57
Running Tasks: 56
Running Tasks: 55
Running Tasks: 54
Running Tasks: 53
Running Tasks: 52
Running Tasks: 51
Running Tasks: 50
Running Tasks: 49
Running Tasks: 48
Running Tasks: 47
Running Tasks: 46
Running Tasks: 45
Running Tasks: 44
Running Tasks: 43
Running Tasks: 42
Running Tasks: 41
Running Tasks: 40
Running Tasks: 39
Running Tasks: 38
Running Tasks: 37
Running Tasks: 36
Running Tasks: 35
Running Tasks: 34
Running Tasks: 33
Running Tasks: 32
Running Tasks: 31
Running Tasks: 30
Running Tasks: 29
Running Tasks: 28
Running Tasks: 27
Running Tasks: 26
Running Tasks: 25
Running Tasks: 24
Running Tasks: 23
Running Tasks: 22
Running Tasks: 21
Running Tasks: 20
Running Tasks: 19
Running Tasks: 18
Running Tasks: 17
Running Tasks: 16
Running Tasks: 15
Running Tasks: 14
Running Tasks: 13
Running Tasks: 12
Running Tasks: 11
Running Tasks: 10
Running Tasks: 9
Running Tasks: 8
Running Tasks: 7
Running Tasks: 6
Running Tasks: 5
Running Tasks: 4
Running Tasks: 3
Running Tasks: 2
Running Tasks: 1
Running Tasks: 0

Everything works. However, if you have thread exception in the wait loop, refer to my first comment.
 
Share this answer
 
v5
Comments
Sonhospa 23-Jul-23 11:51am    
Thank you for having a look. Sorry if you found it unclear, I thought I mentioned that it's Microsoft's example code (which I linked) and that all threads end with Code 0 (which is "no error", right?) – there was no thread exception, the code just silently returns to the UI and does nothing.

Unfortunately, your rewrite leads to exactly the same result. I reckoned that the first line (entriesTasksQuery) might be flawed, but since you put it in the same way I'm now even more clueless. Do you probsably have another idea how to find my error(s) in this?
Graeme_Grant 23-Jul-23 11:52am    
Did you see my update?
Sonhospa 23-Jul-23 12:01pm    
Just searching... usually I'm getting exceptions, but I'll check explicitly.
Edit: Sorry, having a quick visitor so a little delay until I can go on...
Graeme_Grant 23-Jul-23 12:10pm    
Posted a sample fix. After 2am here, so going to bed.
Sonhospa 23-Jul-23 12:59pm    
Thank you ever so much, and sleep well!

FYI: I found the setting for CLR-exceptions (on my German system the names are different) and checked it (it was unchecked) but no exception thrown either. I'll try your approach now and let you know THAT (not if ;-)) it worked for me as well!

UPDATE: First "Good morning and have a lovely day!" :-)
OK, in order to come up with my promise I want to tell you that it did indeed work for me – just as long as it was a separate test project ;-). Thus, settings or other stuff that might differ on our systems wouldn't have hurt. Adapting my own project accordingly (and carefully) unfortunately didn't work out, probably I forgot any changes made in the other classes or whatever. After quite a while, I decided to scrap it and re-install a backup of a well-tested version (i.e. without forgotten code changes) that I had made yesterday. I also had the idea of a simpler overall approach that would give me the required results as well, just in a less "elegant" way. I.e. making me less proud of myself, but still effective.

Thank you, though, for your time and effort! It was really kind of you and also helped me a lot in my learning. Despite your cool workaround I want to report to you that, in the test-project I also tried the older While-Loop using 'Task.WhenAny' as in the Microsoft example, and I got exactly the same results as you did. As I mentioned before: It must have been any other mad change I made in my code without being aware – my bad but I'm good now. It's about time to sleep here in the UK as well now. Thanks again!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900