Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. The Lounge
  3. Multithreaded code is ridiculous

Multithreaded code is ridiculous

Scheduled Pinned Locked Moved The Lounge
designalgorithmsregextutorialquestion
53 Posts 18 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • N Nelek

    I hope I didn't trigger this :rolleyes: ;P

    M.D.V. ;) If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about? Help me to understand what I'm saying, and I'll explain it better to you Rating helpful answers is nice, but saying thanks can be even nicer.

    H Offline
    H Offline
    honey the codewitch
    wrote on last edited by
    #25

    You sort of did, but the truth is i was looking for something to code anyway. At any rate I made this: A Thread Pooling and Task Queuing Demonstration Using Message Passing[^] It's not exactly what you were looking for, i think? but it might be closer. :)

    Real programmers use butterflies

    N 1 Reply Last reply
    0
    • H honey the codewitch

      You sort of did, but the truth is i was looking for something to code anyway. At any rate I made this: A Thread Pooling and Task Queuing Demonstration Using Message Passing[^] It's not exactly what you were looking for, i think? but it might be closer. :)

      Real programmers use butterflies

      N Offline
      N Offline
      Nelek
      wrote on last edited by
      #26

      Did you write all in less than 24 hours? :omg: :omg:

      M.D.V. ;) If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about? Help me to understand what I'm saying, and I'll explain it better to you Rating helpful answers is nice, but saying thanks can be even nicer.

      H 1 Reply Last reply
      0
      • R raddevus

        Greg Utas wrote:

        Well, I'm a longstanding member of the choir that you're preaching to.

        I agree. that's why if I had to do anything that really did heavy multi-threading (as a service or back-end type thing -- not just in a WinForm app) then I would use the new thing: Akka (which implements the Actor Model[^]. I've actually used it one time and it is quite amazing once you get past the learning curve. There's more on that landing page but read this quick summary that really is as good as it sounds.

        Akka site says:

        Actor Model The Actor Model provides a higher level of abstraction for writing concurrent and distributed systems. It alleviates the developer from having to deal with explicit locking and thread management, making it easier to write correct concurrent and parallel systems.

        There are some nice simple diagrams there that show how it works.

        Greg UtasG Offline
        Greg UtasG Offline
        Greg Utas
        wrote on last edited by
        #27

        I'm guessing I've open-sourced something similar in C++. - Software Techniques for Lemmings[^] describes the general principles. - Robust C++: P and V Considered Harmful[^] describes how critical sections are minimized. - Session Processing Tutorial[^] describes the state machine framework, which might be a "double-click" on what some refer to as the Actor pattern. All these concepts are used in the call servers that run in AT&T's wireless network.

        Robust Services Core | Software Techniques for Lemmings | Articles

        <p><a href="https://github.com/GregUtas/robust-services-core/blob/master/README.md">Robust Services Core</a>
        <em>The fox knows many things, but the hedgehog knows one big thing.</em></p>

        1 Reply Last reply
        0
        • H honey the codewitch

          So as an instructional article I'm preparing code that can enqueue work items to a limited number of threads. If all the threads are busy and there's no more thread creation allowed (say you have a 3 thread limit) then one of the threads that's already busy enqueues the next message for when it's done with what it's currently processing. It schedules among the already busy threads using a round robin technique. The whole thing works using message passing and message queues. That's how the threads communicate with each other. You can post messages to each of the threads. The trouble with it is the complexity of it snowballs. All of the sudden I need to sync the UI which requires a whole separate layer. And then there's the interthread communication that's already complicated. There's only so much I can fit into an article without overwhelming the reader, and to produce anything approaching a real world example requires so much complicated code that it's just silly. Oh you did this over here? Well you need to synchronize over there. And because you did that, you need to handle it over there too, etc. It's a mess. I really think the approach traditional computers take to preemptive multithreading is an anti-pattern. It feels like every anti-pattern I've ever encountered: The more code you need to make it work, the more code you need to make it work! You end up putting more work into it just to get to the point where you can put more work into it, and everything feels like a workaround.

          Real programmers use butterflies

          F Offline
          F Offline
          F ES Sitecore
          wrote on last edited by
          #28

          Sounds useful. ThreadPool Class (System.Threading) | Microsoft Docs[^]

          H 1 Reply Last reply
          0
          • N Nelek

            And what if it is not in .Net? ;) :rolleyes:

            M.D.V. ;) If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about? Help me to understand what I'm saying, and I'll explain it better to you Rating helpful answers is nice, but saying thanks can be even nicer.

            R Offline
            R Offline
            raddevus
            wrote on last edited by
            #29

            Nelek wrote:

            And what if it is not in .Net?

            Well, then, it is obviously in Java --> Akka: build concurrent, distributed, and resilient message-driven applications for Java and Scala | Akka[^] :rolleyes: :rolleyes: Yeah, if it's not in either of those two then you must do all the work...or remove the multi-threaded sections of the code. :laugh:

            1 Reply Last reply
            0
            • F F ES Sitecore

              Sounds useful. ThreadPool Class (System.Threading) | Microsoft Docs[^]

              H Offline
              H Offline
              honey the codewitch
              wrote on last edited by
              #30

              Yeah but there's issues using that, including not being able to control the number of threads it uses.

              Real programmers use butterflies

              F 1 Reply Last reply
              0
              • N Nelek

                Did you write all in less than 24 hours? :omg: :omg:

                M.D.V. ;) If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about? Help me to understand what I'm saying, and I'll explain it better to you Rating helpful answers is nice, but saying thanks can be even nicer.

                H Offline
                H Offline
                honey the codewitch
                wrote on last edited by
                #31

                Yes

                Real programmers use butterflies

                1 Reply Last reply
                0
                • H honey the codewitch

                  Yeah but there's issues using that, including not being able to control the number of threads it uses.

                  Real programmers use butterflies

                  F Offline
                  F Offline
                  F ES Sitecore
                  wrote on last edited by
                  #32

                  ThreadPool.SetMaxThreads(Int32, Int32) Method (System.Threading) | Microsoft Docs[^] ThreadPool.SetMinThreads(Int32, Int32) Method (System.Threading) | Microsoft Docs[^]

                  H 1 Reply Last reply
                  0
                  • F F ES Sitecore

                    ThreadPool.SetMaxThreads(Int32, Int32) Method (System.Threading) | Microsoft Docs[^] ThreadPool.SetMinThreads(Int32, Int32) Method (System.Threading) | Microsoft Docs[^]

                    H Offline
                    H Offline
                    honey the codewitch
                    wrote on last edited by
                    #33

                    I was wrong, fair enough but the other issue is I was demonstrating how thread pooling works, and using the ThreadPool and Task undermines all of that. I say as much at the beginning of the article.

                    Real programmers use butterflies

                    1 Reply Last reply
                    0
                    • H honey the codewitch

                      So as an instructional article I'm preparing code that can enqueue work items to a limited number of threads. If all the threads are busy and there's no more thread creation allowed (say you have a 3 thread limit) then one of the threads that's already busy enqueues the next message for when it's done with what it's currently processing. It schedules among the already busy threads using a round robin technique. The whole thing works using message passing and message queues. That's how the threads communicate with each other. You can post messages to each of the threads. The trouble with it is the complexity of it snowballs. All of the sudden I need to sync the UI which requires a whole separate layer. And then there's the interthread communication that's already complicated. There's only so much I can fit into an article without overwhelming the reader, and to produce anything approaching a real world example requires so much complicated code that it's just silly. Oh you did this over here? Well you need to synchronize over there. And because you did that, you need to handle it over there too, etc. It's a mess. I really think the approach traditional computers take to preemptive multithreading is an anti-pattern. It feels like every anti-pattern I've ever encountered: The more code you need to make it work, the more code you need to make it work! You end up putting more work into it just to get to the point where you can put more work into it, and everything feels like a workaround.

                      Real programmers use butterflies

                      L Offline
                      L Offline
                      Lost User
                      wrote on last edited by
                      #34

                      A single ConcurrentQueue (serial) or a ConcurrentBag (random) for messages, and a BackgroundWorker for dispatching worker threads and updating the UI (progress reporting event).

                      It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it. ― Confucian Analects: Rules of Confucius about his food

                      H 1 Reply Last reply
                      0
                      • L Lost User

                        A single ConcurrentQueue (serial) or a ConcurrentBag (random) for messages, and a BackgroundWorker for dispatching worker threads and updating the UI (progress reporting event).

                        It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it. ― Confucian Analects: Rules of Confucius about his food

                        H Offline
                        H Offline
                        honey the codewitch
                        wrote on last edited by
                        #35

                        I'm using a concurrent queue but i'm not using the BackgroundWorker nor the Task framework in my example, because the goal was to illustrate how the threading stuff works under the hood, not to provide production code. I say about as much in the introduction of the article.

                        Real programmers use butterflies

                        L 1 Reply Last reply
                        0
                        • H honey the codewitch

                          I'm using a concurrent queue but i'm not using the BackgroundWorker nor the Task framework in my example, because the goal was to illustrate how the threading stuff works under the hood, not to provide production code. I say about as much in the introduction of the article.

                          Real programmers use butterflies

                          L Offline
                          L Offline
                          Lost User
                          wrote on last edited by
                          #36

                          ConcurrentQueue is not exactly a "primitive". About as primitive as BGW, IMO. And BGW is very fine-grained.

                          It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it. ― Confucian Analects: Rules of Confucius about his food

                          H 1 Reply Last reply
                          0
                          • L Lost User

                            ConcurrentQueue is not exactly a "primitive". About as primitive as BGW, IMO. And BGW is very fine-grained.

                            It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it. ― Confucian Analects: Rules of Confucius about his food

                            H Offline
                            H Offline
                            honey the codewitch
                            wrote on last edited by
                            #37

                            I'm not saying it is. I'm simply saying that in order to demonstrate the whole shebang in a way that doesn't make the concepts specific to .NET required me to reinvent that particular wheel for demonstration purposes. Again I make it clear in the introduction that this approach is for demonstration, not for production, and suggest using the Task framework and the ThreadPool for this stuff.

                            Real programmers use butterflies

                            L 1 Reply Last reply
                            0
                            • H honey the codewitch

                              I'm not saying it is. I'm simply saying that in order to demonstrate the whole shebang in a way that doesn't make the concepts specific to .NET required me to reinvent that particular wheel for demonstration purposes. Again I make it clear in the introduction that this approach is for demonstration, not for production, and suggest using the Task framework and the ThreadPool for this stuff.

                              Real programmers use butterflies

                              L Offline
                              L Offline
                              Lost User
                              wrote on last edited by
                              #38

                              Saying it's "ridiculous" to start with is / was sort of invitation to fix it.

                              It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it. ― Confucian Analects: Rules of Confucius about his food

                              1 Reply Last reply
                              0
                              • H honey the codewitch

                                What I'm doing is I'm queuing up tasks. In the demo each time a user clicks a button (in order to queue up a new task) the code looks for an available worker. If it doesn't have one, and it can create a new one (and consequently a new thread) then it will. Otherwise if there are already a maximum number of workers created it will choose one of the busy workers to handle the next task. All of the workers do the same task. Think of this like a server application that accepts a limited number of incoming requests into a pool of workers, but will then queue requests after the limit is exceeded among the busy workers. One of them will pick it up as soon as it's finished with what it's doing. Make sense? I hope it does! :~ ETA: Wait, I think I see what you mean by using one queue. I'll have to think on this.

                                Real programmers use butterflies

                                U Offline
                                U Offline
                                User 13269747
                                wrote on last edited by
                                #39

                                That isn't the usual way of doing things; the common approach is: 1. Create pool of threads at startup (3, 5, whatever). 2. Create two queues at startup (work-queue and results-queue, using a LL or DLL queue, not an array). 3. Each thread takes the next work item from work-queue, working to completion, and posting the results to results-queue. 4. The main thread simply enqueues work items to the work-queue, and waits on the results-queue (use a semaphore here) for results. There's no blocking involved other than the wait-on-semaphore (and wait-on-mutex for queue modification).

                                H 1 Reply Last reply
                                0
                                • H honey the codewitch

                                  So as an instructional article I'm preparing code that can enqueue work items to a limited number of threads. If all the threads are busy and there's no more thread creation allowed (say you have a 3 thread limit) then one of the threads that's already busy enqueues the next message for when it's done with what it's currently processing. It schedules among the already busy threads using a round robin technique. The whole thing works using message passing and message queues. That's how the threads communicate with each other. You can post messages to each of the threads. The trouble with it is the complexity of it snowballs. All of the sudden I need to sync the UI which requires a whole separate layer. And then there's the interthread communication that's already complicated. There's only so much I can fit into an article without overwhelming the reader, and to produce anything approaching a real world example requires so much complicated code that it's just silly. Oh you did this over here? Well you need to synchronize over there. And because you did that, you need to handle it over there too, etc. It's a mess. I really think the approach traditional computers take to preemptive multithreading is an anti-pattern. It feels like every anti-pattern I've ever encountered: The more code you need to make it work, the more code you need to make it work! You end up putting more work into it just to get to the point where you can put more work into it, and everything feels like a workaround.

                                  Real programmers use butterflies

                                  M Offline
                                  M Offline
                                  maze3
                                  wrote on last edited by
                                  #40

                                  Im having flashbacks now when I had to improve the throughput of some data processing application which I made a bunch of work on, so threaded it. Lucky c# task was a newish thing to me compared to previous time on threads which was doing separate thread class. but yeah figuring out the allocation was interesting. but yeah, one master queue using Synchronised List or Array makes the queue part much easier

                                  H 1 Reply Last reply
                                  0
                                  • H honey the codewitch

                                    So as an instructional article I'm preparing code that can enqueue work items to a limited number of threads. If all the threads are busy and there's no more thread creation allowed (say you have a 3 thread limit) then one of the threads that's already busy enqueues the next message for when it's done with what it's currently processing. It schedules among the already busy threads using a round robin technique. The whole thing works using message passing and message queues. That's how the threads communicate with each other. You can post messages to each of the threads. The trouble with it is the complexity of it snowballs. All of the sudden I need to sync the UI which requires a whole separate layer. And then there's the interthread communication that's already complicated. There's only so much I can fit into an article without overwhelming the reader, and to produce anything approaching a real world example requires so much complicated code that it's just silly. Oh you did this over here? Well you need to synchronize over there. And because you did that, you need to handle it over there too, etc. It's a mess. I really think the approach traditional computers take to preemptive multithreading is an anti-pattern. It feels like every anti-pattern I've ever encountered: The more code you need to make it work, the more code you need to make it work! You end up putting more work into it just to get to the point where you can put more work into it, and everything feels like a workaround.

                                    Real programmers use butterflies

                                    T Offline
                                    T Offline
                                    Thomas Chizek
                                    wrote on last edited by
                                    #41

                                    Okay, I know I am late to the party here and might be a voice in the wilderness, but I think for your case, using manual multi-threading is exactly the right way to go. Why? Because you are teaching, students need to understand the complexity of the underlying functionality to be able to know when it is appropriate to use the simplified interfaces that modern languages, libraries, and syntactic sugar have added over the last thirty years. One of the things that I see in code that has been written by people who just discovered the async calls or the Thread library in whatever language is hot with management is the overuse of threads. They throw calls that are absolutely sure to block right here right now into a separate thread, even though processing on their application can not proceed without the answer. Hey folks, all of our operating systems and most of our language runtimes are smart enough to detect when some thread/process goes out for a long IO operation and let something else use the CPU. There is no need to add the overhead and complexity of putting your IO into a thread. On the other hand, beginners often miss thread operations in large complex compute operations. Activities where spinning the processing of a security token or hash into a temporary thread on a different core/processor thread with an async callback would let the other pre-authorized operations start rather than blocking on that operation. So, in addition to teaching them about the complexity of the dance that happens behind every simple thread spawn, you can also give them some views into the differences between appropriate and inappropriate times to use threads. Why the specific example is a teaching only example, and what real use-cases would be. Just a thought.

                                    H 1 Reply Last reply
                                    0
                                    • T Thomas Chizek

                                      Okay, I know I am late to the party here and might be a voice in the wilderness, but I think for your case, using manual multi-threading is exactly the right way to go. Why? Because you are teaching, students need to understand the complexity of the underlying functionality to be able to know when it is appropriate to use the simplified interfaces that modern languages, libraries, and syntactic sugar have added over the last thirty years. One of the things that I see in code that has been written by people who just discovered the async calls or the Thread library in whatever language is hot with management is the overuse of threads. They throw calls that are absolutely sure to block right here right now into a separate thread, even though processing on their application can not proceed without the answer. Hey folks, all of our operating systems and most of our language runtimes are smart enough to detect when some thread/process goes out for a long IO operation and let something else use the CPU. There is no need to add the overhead and complexity of putting your IO into a thread. On the other hand, beginners often miss thread operations in large complex compute operations. Activities where spinning the processing of a security token or hash into a temporary thread on a different core/processor thread with an async callback would let the other pre-authorized operations start rather than blocking on that operation. So, in addition to teaching them about the complexity of the dance that happens behind every simple thread spawn, you can also give them some views into the differences between appropriate and inappropriate times to use threads. Why the specific example is a teaching only example, and what real use-cases would be. Just a thought.

                                      H Offline
                                      H Offline
                                      honey the codewitch
                                      wrote on last edited by
                                      #42

                                      Thomas Chizek wrote:

                                      So, in addition to teaching them about the complexity of the dance that happens behind every simple thread spawn, you can also give them some views into the differences between appropriate and inappropriate times to use threads. Why the specific example is a teaching only example, and what real use-cases would be. Just a thought.

                                      I already wrote the article my rant was about but this just might be fodder for a new article. Thanks. :)

                                      Real programmers use butterflies

                                      T 1 Reply Last reply
                                      0
                                      • U User 13269747

                                        That isn't the usual way of doing things; the common approach is: 1. Create pool of threads at startup (3, 5, whatever). 2. Create two queues at startup (work-queue and results-queue, using a LL or DLL queue, not an array). 3. Each thread takes the next work item from work-queue, working to completion, and posting the results to results-queue. 4. The main thread simply enqueues work items to the work-queue, and waits on the results-queue (use a semaphore here) for results. There's no blocking involved other than the wait-on-semaphore (and wait-on-mutex for queue modification).

                                        H Offline
                                        H Offline
                                        honey the codewitch
                                        wrote on last edited by
                                        #43

                                        That's actually what I ended up doing. Greg Utas made a similar comment as you and I had an aha moment. Before that, I had engineering tunnel vision wherein I was stuck on doing something like I had imagined but there was an easier way. Still, the code, while much simpler is still ridiculous. :laugh: God bless the Task framework - of course using it this time would have defeated the purpose of what i was doing

                                        Real programmers use butterflies

                                        U 1 Reply Last reply
                                        0
                                        • H honey the codewitch

                                          Thomas Chizek wrote:

                                          So, in addition to teaching them about the complexity of the dance that happens behind every simple thread spawn, you can also give them some views into the differences between appropriate and inappropriate times to use threads. Why the specific example is a teaching only example, and what real use-cases would be. Just a thought.

                                          I already wrote the article my rant was about but this just might be fodder for a new article. Thanks. :)

                                          Real programmers use butterflies

                                          T Offline
                                          T Offline
                                          Thomas Chizek
                                          wrote on last edited by
                                          #44

                                          No problem, glad to help. :)

                                          1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • World
                                          • Users
                                          • Groups