如何保持异步程序运行?

时间:2015-05-12 19:53:59

标签: c# asynchronous

我正在开发一个程序,该程序使用S22 imap来保持与gmail的IDLE连接并实时接收消息。

我从我的Main方法调用以下函数:

static void RunIdle()
{
    using (ImapClient Client = new ImapClient("imap.gmail.com", 993, "user", "pass", AuthMethod.Login, true))
    {

        if (!Client.Supports("IDLE"))
            throw new Exception("This server does not support IMAP IDLE");

        Client.DefaultMailbox = "label";
        Client.NewMessage += new EventHandler<IdleMessageEventArgs>(OnNewMessage);
        Console.WriteLine("Connected to gmail");

        while (true)
        {
            //keep the program running until terminated
        }

    }
}

使用无限while循环有效,但似乎有更正确的方法来执行此操作。在将来,如果我想添加更多IDLE连接,我看到我的解决方案工作的唯一方法是为每个连接使用单独的线程。

用while循环完成我正在做的事情的最佳方法是什么?

3 个答案:

答案 0 :(得分:2)

不要丢弃客户端并将其置于静态变量中。这样它就会继续运行并不断提高事件。根本不需要等待循环。删除using语句。

如果这是你程序中的最后一个线程,你确实需要保持它。

Thread.Sleep(Timeout.Infinite);

答案 1 :(得分:1)

  

用while循环完成我正在做的事情的最佳方法是什么?

您可能希望执行以下两项操作:

  1. RunIdle提供CancelationToken,以便彻底停止。
  2. 在忙碌的等待while循环中,使用Task.Delay“休眠”,直到您需要再次“ping”邮箱。

    static async Task RunIdle(CancelationToken cancelToken, TimeSpan pingInterval)
    {
        // ...
    
        // the new busy waiting ping loop
        while (!cancelToken.IsCancellationRequested)
        {
            // Do your stuff to keep the connection alive.
    
            // Wait a while, while freeing up the thread.
            if (!cancelToken.IsCancellationRequested)
                await Task.Delay(pingInterval, cancelToken);
        }
    }
    
  3. 如果您不需要做任何事情来保持连接活动,除非阻止进程终止:

    • 从控制台读取并等到 ctrl + c 或一些干净的“退出”命令。

答案 2 :(得分:0)

避免线程阻塞的简单解决方案是在一段随机的时间内使用Task.Delay()

static async Task RunIdle(CancellationToken token = default(CancellationToken))
{
    using (ImapClient Client = new ImapClient("imap.gmail.com", 993, "user", "pass", AuthMethod.Login, true))
    {

        ...

        var interval = TimeSpan.FromHours(1);
        while (!token.IsCancellationRequested)
        {
            await Task.Delay(interval, token);
        }
    }
}

如果执行需要在某个时刻停止,则可以使用while(true)而不是CancellationTokenTask.Delay()也支持这一点。

但这是控制台应用程序的所有解决方案。如果作为服务运行,服务主机将确保您的程序在启动后继续执行,因此您可以返回。