信号任务准备就绪但永远不会完成

时间:2017-05-29 12:49:06

标签: .net asynchronous task-parallel-library

我需要打开一些TCP端口,我想在所有端口都打开时发出信号,但这些任务无法完成,因为他们正在侦听传入的tcp数据包。

public partial class TcpServer
{
    protected override void Init()
    {
        var ports = Enumerable.Range(17001, 32);
        List<Task> tasks = new List<Task>();
        foreach (int port in ports)
        {
            tasks.Add(Task.Run(() => new Listener(port)));
        }
        Task.WaitAll(tasks.ToArray());   //this will never complete
        Console.WriteLine("Server ready!"); //I want to signal this when every port is opened
    }
}
public class Program
{
    public static void Main(string[] args)
    {
        var task = Task.Run(() => new TcpServer().Init());
        Tasks.WaitAll(task);
    }
}

public class Listener
{
 public Listener(int port)
    {
        _puerto = port;
        Escuchar(port);
    }
    private void Escuchar(int port)
    {
        listener = new TcpListener(IPAddress.Parse(GetLocalIPAddress()), port);
        listener.Start();
        Console.WriteLine($"Listening at port {_puerto}");
        var error = false;
        while (!error)
        {
            try
            {
                TcpClient client = listener.AcceptTcpClient(); //blocks here waiting for incoming packet
                var stream = new StreamReader(client.GetStream());
                var data = stream.ReadToEnd();
                Evento evento = Parsear(data);
                evento.Procesar();
            }
            catch (Exception e)
            {
                 listener.Stop();
                 error = true;
            }
        }
        Escuchar(port);
    }
}

当所有端口都打开并准备好侦听传入的数据包时,我想发出控制台信号Console.WriteLine(&#34; Server ready!&#34;);

1 个答案:

答案 0 :(得分:0)

最简单的方法可能是不要在一个函数中完成所有操作。将端口的开口移动到构造函数,例如:

    var ports = Enumerable.Range(17001, 32);

    var listeners = ports.AsParallel(port => new Listener(port)).ToList();

    Console.WriteLine("Server ready!"); 

    var listeningTasks = listeners.Select(listener => Task.Run(listener.Listen)).ToArray();

    // now this line will block
    Task.WaitAll(listeningTasks);

对听众稍作修改:

public class Listener
{
    public Listener(int port)
    {
        _puerto = port;
        listener = new TcpListener(IPAddress.Parse(GetLocalIPAddress()), port);
        listener.Start();
        Console.WriteLine($"Listening at port {_puerto}");
    }

    public void Listen()
    {
        var error = false;
        while (!error)
        {
            try
            {
                TcpClient client = listener.AcceptTcpClient(); //blocks here waiting for incoming packet
                var stream = new StreamReader(client.GetStream());
                var data = stream.ReadToEnd();
                Evento evento = Parsear(data);
                evento.Procesar();
            }
            catch (Exception e)
            {
                 listener.Stop();
                 error = true;
            }
        }
        Listen();
    }
}