Task.StartNew()多次调用只返回一次

时间:2015-09-25 16:41:07

标签: c# multithreading task-parallel-library

我使用了以下代码:

var tuple = Tuple.Create("xxx.xx.xx.xxx", 6102, "109", "Metrix1", 1);
var tuple1 = Tuple.Create("xxx.xx.xx.xxx", 6102, "110", "Metrix2", 1);
var tuple2 = Tuple.Create("xxx.xx.xx.xxx", 6102, "111", "Metrix3", 1);
var tuple3 = Tuple.Create("xxx.xx.xx.xxx", 6103, "106", "Metrix4", 2);

gateways.Add(tuple);
gateways.Add(tuple1);
gateways.Add(tuple2);
gateways.Add(tuple3);

foreach (var gatewayId in gateways)
{
    Task.Factory.StartNew(
        () => GetJobs(
            gatewayId.Item1,
            gatewayId.Item2,
            gatewayId.Item3,
            gatewayId.Item4,
            gatewayId.Item5));
}

然后调用GetJobs调用CallGateway并调用ProcessMessageNew

private string GetJobs(string Url , int portNumber, string Engineer , string mEngineer , int GatewayId)
{
    ConfigLogger.Instance.LogInfo("info", "Calling Gateway Start: " + DateTime.Now.ToString("HH:mm:ss.ffff") + " for engineer: " + Engineer);
    string gatewayResult = CallGateway(Engineer, Url, portNumber);
    ConfigLogger.Instance.LogInfo("info", "Calling Gateway End: " + DateTime.Now.ToString("HH:mm:ss.ffff") + " for engineer: " + Engineer);
    if (gatewayResult != null)
    {
        ConfigLogger.Instance.LogInfo("info", "Processing Request Message: " + DateTime.Now.ToString("HH:mm:ss.ffff") + " for engineer: " + Engineer);
        ProcessMessageNew(gatewayResult, Engineer, Url, portNumber , MEngineer ,PGatewayId);
    }
    return gatewayResult;
}

CallGateway

public string CallGateway(string gatewayUrl, int portNumber , string engineer)
{
     string result = null;
     int streamBufferSize = 1000;

     IPHostEntry ipHostInfo = Dns.Resolve(gatewayUrl.ToString());
     IPAddress ipAddress = ipHostInfo.AddressList[0];
     IPEndPoint remoteEP = new IPEndPoint(ipAddress, portNumber);

     // Create a TCP/IP  socket.
     Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
     clientSocket.Connect(ipAddress, portNumber);

     // Set these on app param
     clientSocket.ReceiveTimeout = 300000;
     clientSocket.SendTimeout = 60000;
     // build message string to send to gateway
     string message = BuildMessageGetJobsFromGateway(engineer, SendTypeIn);

     // Create a NetworkStream that owns clientSocket and 
     // then create a BufferedStream on top of the NetworkStream. 
     // Both streams are disposed when execution exits the 
     // using statement. 
     using (var netStream = new NetworkStream(clientSocket, true),
            var bufStream = new BufferedStream(netStream, streamBufferSize))
     {
          // Check whether the underlying stream supports seeking.
          Console.WriteLine("NetworkStream {0} seeking.\n", bufStream.CanSeek ? "supports" : "does not support");

          //variable used to only close once
          bool doClose = true;

          // Send and receive data. 
          if (bufStream.CanWrite)
          {
              try
              {
                  SendData(netStream, bufStream, SendTypeIn, message);
              }
              catch (Exception exSend)
              {
                  Console.WriteLine(exSend.Message.ToString());
              }
           }
           if (bufStream.CanRead)
           {
                try
                {
                     result = ReceiveData(netStream, bufStream, clientSocket);
                }
                catch (Exception exRecieve)
                {
                    //
                }
                finally
                {
                    Console.WriteLine("Closing Stream");
                    doClose = false;
                    bufStream.Close();
                    clientSocket.Close();
                }
            }

            // When bufStream is closed, netStream is in turn 
            // closed, which in turn shuts down the connection 
            // and closes clientSocket.
            Console.WriteLine("\nShutting down the connection.");

            // only close if no exception is raised
            if (doClose)
            {
                bufStream.Close();
                clientSocket.Close();
            }
        }
        return result;
    }
}

但是,我在日志文件4中调用了呼叫网关方法并且只有一个返回工程师106,对网关的调用创建了一个套接字客户端然后接收数据,但它只发生在4个中的一个电话:

[MobileGateway.exe] - [Info] - [25/09/2015 16:47:19] - Calling Gateway Start: 16:47:19.6574 for engineer: 109
[MobileGateway.exe] - [Info] - [25/09/2015 16:47:19] - Processing Call Mobile Gateway: 16:47:19.6624
[MobileGateway.exe] - [Info] - [25/09/2015 16:47:20] - Calling Gateway Start: 16:47:20.6685 for engineer: 110
[MobileGateway.exe] - [Info] - [25/09/2015 16:47:20] - Processing Call Mobile Gateway: 16:47:20.6875
[MobileGateway.exe] - [Info] - [25/09/2015 16:47:21] - Calling Gateway Start: 16:47:21.6696 for engineer: 111
[MobileGateway.exe] - [Info] - [25/09/2015 16:47:21] - Processing Call Mobile Gateway: 16:47:21.6716
[MobileGateway.exe] - [Info] - [25/09/2015 16:47:22] - Calling Gateway Start: 16:47:22.6686 for engineer: 106
[MobileGateway.exe] - [Info] - [25/09/2015 16:47:22] - Processing Call Mobile Gateway: 16:47:22.6706
[MobileGateway.exe] - [Info] - [25/09/2015 16:47:23] - Processing Call Mobile Ended: 16:47:23.0476
[MobileGateway.exe] - [Info] - [25/09/2015 16:47:23] - Calling Gateway End: 16:47:23.0486 for engineer: 106
[MobileGateway.exe] - [Info] - [25/09/2015 16:47:23] - Processing Request Message: 16:47:23.0486 for engineer: 106
[MobileGateway.exe] - [Info] - [25/09/2015 16:47:23] - Message Recieved From Gateway: 16:47:23.0496

应该以并行或异步方式处理调用,因为需要同时调用此方法超过1000次并且它们是长时间运行的进程,所以我需要一次处理多个。

为什么我得到1回应而不是4回答?

1 个答案:

答案 0 :(得分:0)

由于您已经在代码中填写了地址xxx,我无法肯定地说,但可能会发生这种情况,因为前三个网关的端口号6102相同。所以你要关闭并打开相同地址的流三次并行,这样就会抛出异常,以便以后静默捕获。

此外,您可以通过将网关对象以单件形式传递来提高代码的可读性和可维护性,如下所示:

foreach (var gatewayId in gateways) 
{
    Task.Factory.StartNew(() => GetJobs(gatewayId)); 
}

并修改您的GetJobs方法:

private string GetJobs(Gateway gateway)
{
    ConfigLogger.Instance.LogInfo("info", "Calling Gateway Start: " + DateTime.Now.ToString("HH:mm:ss.ffff") + " for engineer: " + gateway.Engineer);
    string gatewayResult = CallGateway(gateway);
    ConfigLogger.Instance.LogInfo("info", "Calling Gateway End: " + DateTime.Now.ToString("HH:mm:ss.ffff") + " for engineer: " + gateway.Engineer);
    if (gatewayResult != null)
    {
        ConfigLogger.Instance.LogInfo("info", "Processing Request Message: " + DateTime.Now.ToString("HH:mm:ss.ffff") + " for engineer: " + gateway.Engineer);
        ProcessMessageNew(gatewayResult, gateway);
    }
    return gatewayResult;
}

此外,进一步向下,更改您的ProcessMessageNewCallGateway,以匹配上述代码中的新定义。