-2

Sorry for the confusing title, but that's basically what i need, i could do something with global variables but that would only be viable for 2 threads that are requested one after the other.

here is a pseudo code that might explain it better.

 /*Async function that gets requests from a server*/
        if ()//recieved request from server
        {
            new Thread(() =>
            {
                //do stuff
                //in the meantime a new thread has been requested from server
                //and another one 10 seconds later.. etc.

                //wait for this current thread to finish
                //fire up the first thread that was requested while this ongoing thread
                //after the second thread is finished fire up the third thread that was requested 10 seconds after this thread
                //etc...
            }).Start();
        }

I don't know when each thread will be requested, as it is based on the server sending info to client, so i cant do Task.ContiuneWith as it's dynamic.

So Michael suggested me to look into Queues, and i came up with it

    static Queue<Action> myQ = new Queue<Action>();
    static void Main(string[] args)
    {
        new Thread(() =>
       {
           while (1 == 1)
           {
               if (myQ.FirstOrDefault() == null)
                   break;
               myQ.FirstOrDefault().Invoke();
           }
       }).Start();

        myQ.Enqueue(() =>
        {
            TestQ("First");
        });
        myQ.Enqueue(() =>
        {
            TestQ("Second");
        });
        Console.ReadLine();
    }
    private static void TestQ(string s)
    {
        Console.WriteLine(s);  
        Thread.Sleep(5000);
        myQ.Dequeue();
    }

I commented the code, i basically need to check if the act is first in queue or not.

EDIT: So i re-made it, and now it works, surely there is a better way to do this ? because i cant afford to use an infinite while loop.

  • 3
    So you do not want multithreading, this sounds more like you want a queue. – oerkelens Nov 07 '17 at 23:30
  • 1
    @oerkelens i guess? i start a thread everytime a server sends a request to, but i don't want this threads to perform in parallel. – TricksterJoe Nov 07 '17 at 23:31
  • 4
    If you do them one by one, there is no need to start new threads. Just queue the requests and handle them one by one. There are several ways to implement queueing, but I'm sure google can help a lot with that :) – oerkelens Nov 07 '17 at 23:38
  • 2
    If I can make a suggestion, maybe have a look at the generalized "Producer-Consumer" problem in Computer Science. Understanding the domain of that problem-space may lead you to more of what you are interesteed in. https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem – cowboydan Nov 08 '17 at 00:59
  • 2
    You've omitted the most important part: **how is the server communicating with the client and vice versa**? You've completely glossed that over, but the actual mechanism whereby the client enqueues work on the server and gets the results is the hard part; writing a producer-consumer queue implementation that services the stuff once it is in the queue is off-the-shelf parts. – Eric Lippert Nov 08 '17 at 01:00
  • And what does "I can't afford a while loop" mean? That makes no sense to me. – Eric Lippert Nov 08 '17 at 01:01
  • And you've gotten the server and client backwards. Clients enqueue work on the server; that's why clients are called **clients** and servers are called **servers**. You don't go to a restaurant and have the server give you a bunch of work to do in the kitchen; it's the server's job to service the requests of the client. **This question is very confusing**. Clarify it. – Eric Lippert Nov 08 '17 at 01:02
  • I just used it as an example, didn't really thought about it in depth, but yes i got it mixed up, sorry about that! – TricksterJoe Nov 08 '17 at 01:04

2 Answers2

2

You will have to use a global container for the threads. Maybe check Queues.

This class implements a queue as a circular array. Objects stored in a Queue are inserted at one end and removed from the other.

Queues and stacks are useful when you need temporary storage for information; that is, when you might want to discard an element after retrieving its value. Use Queue if you need to access the information in the same order that it is stored in the collection. Use Stack if you need to access the information in reverse order. Use ConcurrentQueue(Of T) or ConcurrentStack(Of T) if you need to access the collection from multiple threads concurrently.

Three main operations can be performed on a Queue and its elements:

  • Enqueue adds an element to the end of the Queue.
  • Dequeue removes the oldest element from the start of the Queue.
  • Peek returns the oldest element that is at the start of the Queue but does not remove it from the Queue.

EDIT (From what you added) Here is how I would change your example code to implement the infinite loop and keep it under your control.

static Queue<Action> myQ = new Queue<Action>();
static void Main(string[] args)
{ 
    myQ.Enqueue(() =>
    {
        TestQ("First");
    });
    myQ.Enqueue(() =>
    {
        TestQ("Second");
    });
    Thread thread = new Thread(() =>
    {                             
        while(true) {
            Thread.Sleep(5000)
            if (myQ.Count > 0) {
                myQ.Dequeue().Invoke()
            }
        }
    }).Start();
    // Do other stuff, eventually calling "thread.Stop()" the stop the infinite loop.
    Console.ReadLine();
}
private static void TestQ(string s)
{
    Console.WriteLine(s);
}
JMichelB
  • 475
  • 3
  • 8
  • 2
    How would this work if i will need to execute the request right away? as it looks like you need to Enqueue and only then you fire it up, or am i missing something? – TricksterJoe Nov 07 '17 at 23:47
  • 2
    Use `Peek` to see the first thread and verify if it is running. Start it if it is stopped and hasn't completed. `Dequeue` it if it has completed and start the next one with `Peek`. And yes, you create the thread, enqueue it then verify the first one. – JMichelB Nov 07 '17 at 23:53
  • 2
    Michel, i edited my post with some code i came up with and the issue i am facing right now :) – TricksterJoe Nov 08 '17 at 00:35
  • 2
    @TricksterJoe I had something else in mind, but you have another possible solution. Simply create a global `Queue` object and add actions to it. In the thread, do an infinite loop and check if there is an action in the queue. If there is, get the action (`Action myVar = myQueue.Dequeue()`) and act upon it. I wouldn't suggest passing the queue object as you did. – JMichelB Nov 08 '17 at 00:48
  • 2
    Thanks for the input, could you review the newly edited version? i made it a global variable, start a new thread with an infinite loop that invokes the first object in the Queue, and it looks like it works as intended. – TricksterJoe Nov 08 '17 at 00:55
  • @TricksterJoe I've proposed my changes. – JMichelB Nov 08 '17 at 00:57
2

You could put the requests that you receive into a queue if there is a thread currently running. Then, to find out when threads return, they could fire an event. When this event fires, if there is something in the queue, start a new thread to process this new request.

The only thing with this is you have to be careful about race conditions, since you are communicating essentially between multiple threads.

Lauraducky
  • 674
  • 11
  • 25