【问题标题】:Asynchronous tasks, waiting in main thread for completition异步任务,在主线程中等待完成
【发布时间】:2014-05-29 11:08:36
【问题描述】:

我已经为此任务设置了非常详细的示例,它可能在架构和一些 .NET 使用方面写得不好,但我才刚刚开始。

示例:http://pastebin.com/uhBGWC5e

这里有问题的代码是 Main 方法:

public static void Main (string[] args)
{
    Log("Initializing...");

    // Define listeners.
    TcpListener s1 = CreateAndStartServer(IPAddress.Any, 1337);
    TcpListener s2 = CreateAndStartServer(IPAddress.Any, 1338);

    // Start async.
    Task.Factory.StartNew(Accept, s1);
    Task.Factory.StartNew(Accept, s2);

    // Wait for connections only if servers active.
    while (servers.Any(s => s.Key.Active))
    {
        // 100% usage.
    }

    Log("Nothing left to do, stopping service.");
}

更具体地说,“while”循环。

我在这里尝试做的是,我创建并启动一些 TCP 侦听器,并将它们添加到列表中。

然后,服务器本身有一个允许远程关闭的实现。

循环用于检查程序是否有工作要做。如果没有什么可做的,它应该退出。 (将来当我开始实际实现时,将会有一些 UDP 侦听器、任务队列、计时器等 TCP 侦听器,所有这些都将等待完成。

问题是,while 循环导致 100% 的使用 - 它提供了功能,但消耗太多。我可以将其替换为 Console.ReadKeyConsole.ReadLine,但这不是我要寻找的行为。

还有哪些其他选项可以等待“无事可做”状态?

【问题讨论】:

    标签: c# .net asynchronous mono .net-4.5


    【解决方案1】:

    尝试使用此代码:

        ...
    
        // Start async.
        var task1 = Task.Factory.StartNew(Accept, s1);
        var task2 = Task.Factory.StartNew(Accept, s2);
    
        Task.WhenAll(task1, task2).Wait();    
    
        Log("Nothing left to do, stopping service.");
    }
    

    这应该做同样的事情,但不要使用 100% 的 CPU。但是您必须实现 Accept 以便它阻塞直到应用程序终止。

    【讨论】:

    • 不起作用,应用程序在启动后立即停止(没有先停止 TCP 侦听器)。
    • 当然 Accept 必须是阻塞的,直到应用程序需要被终止...
    • 嗯,我认为它是 - 有关如何使其阻塞的任何示例?
    • 抱歉,没有正确阅读您的代码。需要在Accept方法中实现一个accept循环...
    • 它在链接到@问题的 pastebin 中,但这里是链接的副本,您可以在其中找到 Accept:pastebin.com/uhBGWC5e
    【解决方案2】:

    简单的解决方案是在主线程循环中使用Thread.Sleep(1000)

    您也可以将您的任务标记为foreground threads。当所有前台线程都处于活动状态时,应用程序保持活动状态。阅读更多关于foreground and background threadshere。还可以查看this question,了解如何使任务成为前台线程。

    【讨论】:

    • 我想不惜一切代价避免Thread.Sleep,而前台/后台任务似乎可以帮助我。会看到的。