简体   繁体   中英

Thread sleep C#

I have a question about Threads, I got a multithread TCP accplication that have connections with multiple clients. The threads have operations that take quite long. (maybe a minute or so). How should I put my Sleeps to let all Threads have the same amount of time without puting delay if its for example only one thread runing?.

while(CanDoSomething)
{
    DoIt();                  //Can take all from a few seconds to a few minutes
    Thread.Sleep(100);
}

Is this the best way to do the Sleeps? Or should I give it a longer sleep-time? Does the other threads only get 100ms or does it give them the time to start and then finnish? Becouse I have a feeling that one thread get the work done much faster then the others... Is there anything else I can do to ensure they all get it done with the same priority?

EDIT, MORE CODE:

private void ListenForClients()
    {
        try
        {

            this.tcpListener.Start();
            while (true)
            {
                TcpClient client = this.tcpListener.AcceptTcpClient();

                Connection c = new Connection(this.parent);
                connectionCollection.Add(c);
                Thread clientThread = new Thread(new ParameterizedThreadStart(c.HandleClientComm));

                threadCollection.Add(clientThread);
                clientThread.Start(client);
            }
        }
        catch (Exception e)
        {
        }
    }
public Connection()
    {
        this.todo = new ArrayList();
        todoT = new Thread(handleToDo);
        todoT.Start();
    }

 public void HandleClientComm(object client)
    {
        try
        {

            TcpClient server = (TcpClient)client;

            NetworkStream ns = server.GetStream();
            byte[] data = new byte[1024];
            string input, stringData;
            online = true;
            DateTime lastTime = DateTime.Now;

            while (true && this.online)
            {
                try
                {
                    if (lastTime.AddMinutes(2) < DateTime.Now)
                        break;

                    data = new byte[1024];
                    if (ns.DataAvailable && ns.CanRead)
                    {
                        int recv = ns.Read(data, 0, data.Length);
                        if (recv > 0)
                        {
                            lastTime = DateTime.Now;
                            if ((byte)data[recv - 1] == (byte)255)
                            {
                                int cnt = -1;
                                for (int i = 0; i < recv; i++)
                                {
                                    if (data[i] == (byte)254)
                                    {
                                        cnt = i;
                                        break;
                                    }
                                }

                                int nr = recv - cnt - 2;
                                byte[] tmp = new byte[nr];

                                for (int i = 0; i < nr; i++)
                                {
                                    tmp[i] = data[cnt + i + 1];
                                }
                                string crc = Encoding.UTF8.GetString(tmp);
                                stringData = Encoding.UTF8.GetString(data, 0, cnt);

                                MsgStruct msgs = new MsgStruct(stringData);
                                msgs.setCrc(crc);
                                Thread.Sleep(200);

                                addTodo(msgs);
                                if (msgs.getMsg()[0] == 'T' && this.type == 1)
                                    this.parent.cStructHandler.sendAck(msgs, this.ID);
                                Console.WriteLine(todo.Count);

                            }
                        }
                    }
                    if (parent.cStructHandler.gotMsg(this.ID))
                    {
                        MsgStruct tmpCs = parent.cStructHandler.getNextMsg(this.ID);

                        if (tmpCs.getMsg().Length != 0 && ns.CanWrite)
                        {
                            byte[] ba = Encoding.UTF8.GetBytes(tmpCs.getMsg());

                            if (tmpCs.getCrc() == "")
                            {
                                ulong tmp = CRC.calc_crc(ba, ba.Length);
                                tmpCs.setCrc(tmp.ToString("X"));
                            }

                            if (tmpCs.canSendByTimeout())
                            {
                                string crcStr = "?" + tmpCs.getCrc() + "?";
                                byte[] bb = Encoding.UTF8.GetBytes(crcStr);
                                crcStr = Encoding.UTF8.GetString(bb);
                                byte[] fullMsg = new byte[ba.Length + bb.Length];
                                bb[0] = 254;
                                bb[bb.Length - 1] = 255;

                                ba.CopyTo(fullMsg, 0);
                                bb.CopyTo(fullMsg, ba.Length);
                                string s = System.Text.UTF8Encoding.ASCII.GetString(fullMsg);

                                ns.Write(fullMsg, 0, fullMsg.Length);
                                Thread.Sleep(200);
                                if (!tmpCs.isAckNeeded())
                                    parent.cStructHandler.removeNextMsg(this.ID);
                            }
                        }
                    }
                    Thread.Sleep(100);
                }
                catch (Exception e)
                {
                    break;
                }

            }
            ns.Close();
            server.Close();
            dead = true;
        }
        catch (Exception e)
        {
            dead = true;
        }
    }



public void handleToDo()
    {
        try
        {
            int cnt = 0;
            while (true)
            {
                if (todo.Count > 0)
                {
                     //SWITCH CASE FOR DIFFERENT MESSAGE TYPES, DOING TASKS DEPENDING ON WHAT ONES...
                     Thread.Sleep(100);
                } 
                else
                {
                    if (dead)
                    {
                        todoT.Abort();
                        todoT = null;
                        break;
                    }
                }
                Thread.Sleep(200);
           }
      }
}

Please ask questions if its unclear.

/Nick

There should be a centralized place where task producers store new tasks, and from where task consumers take tasks to process them. The problem is a bit simpler if all tasks are produced before consumers begin their work. Your working threads are task consumers. Task is usually represented with one object that contains all relevant data needed to complete the task. Working thread should not have any form of Sleep, because it is not important which thread is faster and how many tasks it completes. Threads consume tasks in a loop as long as there are tasks to be consumed. This consuming is protected by some lock .

EDIT: I would propose the restructuring of code so that there is only one thread that does all the reading, in asynchronous way ( BeginRead or ReadAsync ). The code would start reading on each socket, and wait until some socket receives data or closes. If data are received for a socket and data are complete then produce new task. You must buffer incomplete data and read more until data are complete. When task is produced one task consumer should eventually pick up the task, process it and send the result to corresponding socket. So socket is read from in one thread and written to in several threads. To prevent some race conditions main reader thread must not read more data for specific socket if there is outstanding incomplete task produced for it. When task is completed main thread may start reading more data.

I haven't covered all the corners, because that would produce a wall of text. Maybe there is a library that does all the communication for you, but I don't know any.

Your OS has a scheduler. It's already working to try to give each thread equal time, and has a better idea of when a thread is waiting on something (and hence would just waste time given to it).

I'm not sure what your deeper problem is, but I'm sure this isn't the solution. There are very few cases of real code where Sleep() is useful (I say "real code" because there are a few other cases where it can help with investigative and test code, rather than production). Most of those very few cases are already there for us in library code anyway. None of them need to call with a value higher than 10 and few with one higher than 0 .

This isn't one of those cases.

You shouldn't use any Sleeps and while loops like this. Even with the while loop there is no use for a Sleep in your case.

Without really knowing your requirement, I suggest you look into timers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM