任务管理和使用?
Task Management and Usage?
所以我得到了一个服务器,它在一个 while 循环中完成以下任务,它作为我的客户端侦听器运行。这个问题似乎想在客户端中尽可能快地循环,这太棒了!但是它在上一个任务完成之前太快地触发任务,新的任务发生(对于同一个客户端)。
我不希望它等待任务完成!我希望它执行更多任务,但不再为已经有任务的特定客户创建任务。
解决此问题的最佳方法是什么...我看到很多人使用 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;
}
});
}
如果您不想在前一个客户端完成之前为给定客户端启动新操作,那么只需跟踪它即可。要么将客户端对象移动到某个 "in progress" 列表,这样它甚至不在您正在循环中处理的客户端列表中,要么向客户端对象 class 添加一个标志,指示该操作是 "in progress",因此您的循环可以忽略客户端,直到当前操作完成(例如 if (c.OperationInProgress) continue;
)。
也就是说,您似乎正在使用轮询(即检查 DataAvailable
)来管理您的 I/O。这是一种非常低效的方法,最重要的是您当前问题的根本原因。如果你使用更好的异步模型,你的代码会更高效 并且 你甚至不会有这个问题,因为异步 API 会提供所有的状态您需要的管理以避免给定客户端的重叠操作。
不幸的是,您的代码示例非常稀疏,缺少提供有关如何更改实现以使用异步模型(以及有多少代码,包括很多在 a good code example 中找不到的额外代码)。所以希望以上内容足以让您找到正确的解决方案。
所以我得到了一个服务器,它在一个 while 循环中完成以下任务,它作为我的客户端侦听器运行。这个问题似乎想在客户端中尽可能快地循环,这太棒了!但是它在上一个任务完成之前太快地触发任务,新的任务发生(对于同一个客户端)。
我不希望它等待任务完成!我希望它执行更多任务,但不再为已经有任务的特定客户创建任务。
解决此问题的最佳方法是什么...我看到很多人使用 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;
}
});
}
如果您不想在前一个客户端完成之前为给定客户端启动新操作,那么只需跟踪它即可。要么将客户端对象移动到某个 "in progress" 列表,这样它甚至不在您正在循环中处理的客户端列表中,要么向客户端对象 class 添加一个标志,指示该操作是 "in progress",因此您的循环可以忽略客户端,直到当前操作完成(例如 if (c.OperationInProgress) continue;
)。
也就是说,您似乎正在使用轮询(即检查 DataAvailable
)来管理您的 I/O。这是一种非常低效的方法,最重要的是您当前问题的根本原因。如果你使用更好的异步模型,你的代码会更高效 并且 你甚至不会有这个问题,因为异步 API 会提供所有的状态您需要的管理以避免给定客户端的重叠操作。
不幸的是,您的代码示例非常稀疏,缺少提供有关如何更改实现以使用异步模型(以及有多少代码,包括很多在 a good code example 中找不到的额外代码)。所以希望以上内容足以让您找到正确的解决方案。