【问题标题】:Task Management and Usage?任务管理和使用?
【发布时间】:2015-01-20 01:44:58
【问题描述】:

所以我得到了一个服务器,它在一段时间循环中执行以下任务,它充当我的客户端侦听器。这个问题似乎想尽可能快地通过客户端循环,这很棒!但是在前一个任务完成之前它会太快地触发任务,而新的任务会发生(对于同一个客户端)。

我不希望它等待任务完成!我希望它拍摄更多任务,但不再为已经有现有任务的特定客户创建任务。

解决此问题的最佳方法是什么...我看到很多人使用 WhenAll 或其他东西,但我并不关心所有任务。

//the below is in a while loop which goes through the clients that are connected.
  if (stream.DataAvailable)
                    {
// the below task is the one that is firing before the pervious fired one completes.
                         Task DataInterpetTask = Task.Factory.StartNew(() =>
                        {
                            int totalBuffer, totalRecieved = 0;
                            byte[] totalBufferByte = new byte[4];
                            byte[] buffer = new byte[0];
                            byte[] tbuffer;
                            int rLength, prevLength;
                            stream.Read(totalBufferByte, 0, 4);
                            totalBuffer = BitConverter.ToInt32(totalBufferByte, 0);
                            Console.WriteLine("got stuff: " + totalBuffer);
                            byte[] buf = new byte[c.getClientSocket().ReceiveBufferSize];
                            while (totalBuffer > totalRecieved)
                            {

                                rLength = stream.Read(buf, 0, buf.Length);
                                totalRecieved = rLength + totalRecieved;
                                if (rLength < buf.Length)
                                {
                                    byte[] temp = new byte[rLength];
                                    Array.Copy(buf, temp, rLength);
                                    buf = temp;
                                }
                                prevLength = buffer.Length;
                                tbuffer = buffer;
                                buffer = new byte[buffer.Length + rLength];
                                Array.Copy(tbuffer, buffer, tbuffer.Length);
                                buf.CopyTo(buffer, prevLength);
                            }

                            String msg = Encoding.ASCII.GetString(buffer);
                            if (msg.Contains("PNG") || msg.Contains("RBG") || msg.Contains("HDR"))
                            {
                                Console.WriteLine("Receiving Picture");
                                RowContainer tempContainer;
                                if ((tempContainer = MainWindow.mainWindow.RowExists(c)) != null)
                                {
                                    tempContainer.Image = buffer;
                                    Console.WriteLine("Updating row: " + tempContainer.rowNumber);
                                    MainWindow.mainWindowDispacter.BeginInvoke(new Action(() =>
                                        MainWindow.mainWindow.UpdateRowContainer(tempContainer, 0)));
                                }
                                else
                                {
                                    Console.WriteLine("Adding row for Picture");
                                    MainWindow.mainWindowDispacter.BeginInvoke(new Action(() =>
                                       MainWindow.mainWindow.CreateClientRowContainer(c, buffer)));
                                }
                                return;
                            }


                            String switchString = msg.Substring(0, 4);
                            if (msg.Length > 4)
                                msg = msg.Substring(4);
                            MainWindow.mainWindowDispacter.BeginInvoke(new Action(() =>
                            {
                                if (MainWindow.debugWindow != null)
                                    MainWindow.debugWindow.LogTextBox.AppendText("Received message " + msg + " from client: " + c.getClientIp() + " as a " + switchString + " type" + Environment.NewLine);

                            }));
                            RowContainer tContain = MainWindow.mainWindow.RowExists(c);
                            if(tContain == null)
                                return;
                            switch (switchString)
                            {
                                case "pong":
                                    c.RespondedPong();
                                    break;
                                case "stat":
                                    tContain.SetState(msg);
                                    MainWindow.mainWindow.UpdateRowContainer(tContain, 1);
                                    break;
                                case "osif":
                                    tContain.Os = msg;
                                    MainWindow.mainWindowDispacter.BeginInvoke(new Action(() =>
                                       MainWindow.mainWindow.UpdateRowContainer(tContain, 2)));
                                    break;
                                case "idle":
                                    tContain.idle = msg;
                                    MainWindow.mainWindowDispacter.BeginInvoke(new Action(() =>
                                       MainWindow.mainWindow.UpdateRowContainer(tContain, 3)));
                                    break;
                            }
                        });
                    }

【问题讨论】:

    标签: c# multithreading concurrency


    【解决方案1】:

    如果您不想在前一个客户端完成之前为给定客户端启动新操作,那么只需跟踪该操作即可。要么将客户端对象移动到某个“进行中”列表,因此它甚至不在您正在循环中处理的客户端列表中,或者向客户端对象类添加一个标志,指示操作正在“进行中” ,这样您的循环就可以忽略客户端,直到当前操作完成(例如if (c.OperationInProgress) continue;)。

    也就是说,您似乎正在使用轮询(即检查DataAvailable)来管理您的 I/O。这是一种非常低效的方法,最重要的是,这是您当前问题的根本原因。如果您使用更好的异步模型,您的代码会更高效并且您甚至不会遇到这个问题,因为异步 API 将提供您需要的所有状态管理以避免给定客户端的重叠操作。

    不幸的是,您的代码示例非常稀疏,缺少提供关于如何更改实现以使用异步模型的特定建议所需的所有细节(以及有多少代码, 包含许多在a good code example 中找不到的额外代码)。因此,希望以上内容足以让您找到正确的解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-28
      相关资源
      最近更新 更多