1

I'm having a software project that needs to communicate to different network hosts and react on events like UI events, various network messages from different sockets, timers, ...

My problem is that I cannot find a satisfying solution to ensure thread safety while still offering non-blocking methods. I have classes that kind of all depend from each other and in my imagination I see lots of threads running uncontrolled cross-country through my classes's methods. So I'd have to create locks for just everything.

I think by adding too many locks my methods could almost behave like blocking ones and produce errors like dead locks.

I need to use .NET 3.5, but I'd be curious what the solution to this looks like in any language / framework (maybe using .Net > 3.5 would be the solution?)

At first I tried imagining the flow of my threads that are created by using Begin...() methods. So my first approach was to define a hand full of threads that maintain a certain part of my application (e.g. Network thread, Event thread, ... ). That way I theoretically could reduce the need of locks as resources are bound to their only one thread.

As those threads had to care about different actions, I tried implementing my own event queue (see How to implement a message pump in Non-UI thread in .NET?) but feel like if .Net does not offer at least some sort of pattern for that purpose, there is likely a better solution to those problems.

I keep on reading all the MSDN pages about design patterns etc, which helps, but still I don't see the whole picture.

I think this is a common scenario in .Net or concurrent programming in general. Maybe I'm just not seeing the solution that resides right in front of me. If so I'd be happy if someone could point me into the right direction.

It is a complex topic and hard to explain. Hope I could give sufficient information. If anything is unclear, please ask.

Thank you for your help.

Community
  • 1
  • 1
  • Just design your resource as an actor (actor model). Basically, a single threaded component with mailbox (queue) to receive commands. – plalx Feb 16 '17 at 14:23
  • Why not posting an answer? Thanks for the hint. The Wikipedia article about the actor model resembles my own thoughts. As I assumed in my question, approaches like that seem not to be of common use in .Net. Although there are third party libraries and I like the approach. – Colonel Panic Feb 16 '17 at 15:50
  • Do you need messages/commands to be durable? For instance, if the UI performs an action, does it absolutely need to receive an ACK that guarantees his command will eventually get processed even if the system goes down? – plalx Feb 16 '17 at 16:23
  • Another impression I have is that the UI thread often is the main thread of the application. That also seems to be an excuse for not having a customizable event queue. But what if you write an application that does not have a UI, like a framework for example? Also sometimes it seems useful to me to have multiple parallel threads with it's own message queue, each – Colonel Panic Feb 16 '17 at 16:34
  • You haven't answered my question. Basically, is your system state only in memory or does it get persisted to disk? That changes the way you need to implement message queues for your actors. If everything is in memory then message queues can be too and do not have to be durable. Otherwise you need to store messages on disk. I've used a relational DB table as poor's man queue where I work and it did the job quite well. – plalx Feb 16 '17 at 17:01
  • There is no need for persistence. The question is only targeted on concurrency (from multithreading) issues. Regarding topics like thread synchronization, asynchronous programming, control flow of threads, etc. Those procedures need to happen fast. Imagine network communications from and to multiple peers, user interaction, ... like everyone knows it from game engines, for example. – Colonel Panic Feb 17 '17 at 10:24
  • Well it that case that makes it very easy to implement actors as their mailbox doesn't have to be durable and can just live in memory. – plalx Feb 17 '17 at 14:09

1 Answers1

3

I find useful the producer/consumer pattern. Basically, you can have asymmetric amounts of producers and consumers, that allows you for example to have multiple threads feeding a queue, and only one thread consuming them; or multiple threads competing to process the messages in a queue.

How to: Implement a Producer-Consumer Dataflow Pattern

In your case, messages coming from sockets and UI events would be pieces of data that needs to be processed, then you can have a single thread (in your case probably the UI thread) reading from that queue, and doing operations on the UI. This way, that thread does not need to lock on everything.

vtortola
  • 34,709
  • 29
  • 161
  • 263
  • Unfortunately I can not (yet) upvote. This sounds quite helpful. It seems hard to put everything into this pattern. But I guess the solution to the whole problem cannot be a single pattern, but adequate patterns/tools for different parts of the application. – Colonel Panic Feb 16 '17 at 15:56
  • I'll tag this as answer. Maybe that gives me more reputition so I can upvote ;) Also I think I need to become more firm in topics like TPL, concurrency models/patterns, and that like. So let's define that as part of the "quintessence". Thanks to everyone. – Colonel Panic Feb 17 '17 at 10:36