Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dispatch work from many threads to one synchronous thread

Say I have 10 threads busily doing something and they sometimes call a method

public HandleWidgets(Widget w) {  HeavyLifting(w) }

However, I don't want my 10 threads to wait on HeavyLifting(w), but instead, dispatch the HeavyLifting(w) work to an 11th thread, the HeavyLifter thread and continue asynchronously. The HeavyLifter thread dispatched to should always be the same thread, and I don't want to make multiple threads (hence, I can't do something quite like this: C# Asynchronous call without EndInvoke?).

HeavyLifting(w) is "fire and forget" in that the threads that call HandleWidgets() don't need a callback or anything like that.

What's a healthy practice for this?

like image 387
John Avatar asked Dec 20 '13 23:12

John


People also ask

Can you make multiple thread to execute same instructions?

Yes, A program can run two threads at the same time. it is called Multi threading.

How many threads can be executed at a time?

4.2. On Windows machines, there's no limit specified for threads. Thus, we can create as many threads as we want, until our system runs out of available system memory.

How can we ensure that instance of this class can be safely used by multiple threads?

Using Volatile keyword A volatile keyword is a field modifier that ensures that the object can be used by multiple threads at the same time without having any problem. volatile is one good way of ensuring that the Java program is thread-safe.

How many threads are initialized when you start an application?

When a Java program starts up, one thread begins running immediately. This is usually called the main thread of our program because it is the one that is executed when our program begins.


2 Answers

I'm surprised none of the other answers here mention TPL DataFlow. You connect a bunch of blocks together and post data through the chain. You can control the concurrency of each block explicitly, so you could do the following:

var transformBlk =
    new TransformBlock<int,int>(async i => {
        await Task.Delay(i);
        return i * 10;
    }, new ExecutionDataflowBlockOptions{MaxDegreeOfParallelism = 10});

var processorBlk=
    new ActionBlock<int>(async i => {
        Console.WriteLine(i);
    },new ExecutionDataflowBlockOptions{MaxDegreeOfParallelism = 1});

transformBlk.LinkTo(processorBlk);
var data = Enumerable.Range(1, 20).Select(x => x * 1000);
foreach(var x in data)
{
    transformBlk.Post(x);
}
like image 154
spender Avatar answered Oct 31 '22 01:10

spender


Basically you have threads that are producers of work and one thread that is a consumer of it.

Create a thread and have it Take from a BlockingCollection in a loop. This is your consumer thread which will call HeavyLifting. It will simply wait until an item is available and then proces it:

A call to Take may block until an item is available to be removed.

The other threads can simply add items to the collection.

Note that BlockingCollection doesn't guarantee ordering of items added/removed by itself:

The order in which an item is removed depends on the type of collection used to create the BlockingCollection instance. When you create a BlockingCollection object, you can specify the type of collection to use

like image 26
ta.speot.is Avatar answered Oct 30 '22 23:10

ta.speot.is