[英]How to keep an asynchronous program running?
I'm working on a program that uses S22 imap to keep an IDLE connection to gmail and receive messages real time. 我正在使用S22 imap保持与gmail的IDLE连接并实时接收消息的程序。
I am calling the following function from my Main method: 我正在从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
}
}
}
Using the infinite while loop works, but it seems there would be a more correct way to do this. 使用无限的while循环可以工作,但是似乎会有更正确的方法来做到这一点。 In the future if I want to add more IDLE connections, the only way I see my solution working is with a separate thread for each connection.
将来,如果我想添加更多的IDLE连接,则看到我的解决方案有效的唯一方法是为每个连接使用单独的线程。
What is the best way to accomplish what I am doing with the while loop? 完成while循环的最佳方法是什么?
Do not dispose of the client and root it in a static variable. 不要丢弃客户端并将其植根于静态变量中。 That way it just stays running and keeps raising events.
这样,它就保持运行并不断引发事件。 There is no need to have a waiting loop at all.
根本不需要等待循环。 Remove the
using
statement. 删除
using
语句。
If this is the last thread in your program you indeed need to keep it alive. 如果这是程序中的最后一个线程,则确实需要保持其活动状态。
Thread.Sleep(Timeout.Infinite);
What is the best way to accomplish what I am doing with the while loop?
完成while循环的最佳方法是什么?
You may want to do the following two things: 您可能需要做以下两件事:
RunIdle
with a CancelationToken
so that it can be cleanly stopped. RunIdle
与CancelationToken
,以便它可以干净地停止。 In your busy waiting while
loop, use Task.Delay
to "sleep" until you need to "ping" the mailbox again. 在忙于等待的
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); } }
If you don't need to do anything to keep the connection alive, except from keeping the process from terminating: 如果您不需要执行任何操作来保持连接活动,除了可以防止进程终止:
A simple solution that avoid thread blocking would be to just use Task.Delay()
for some random amount of time. 一个避免线程阻塞的简单解决方案是只使用
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);
}
}
}
Instead of while(true)
you could perhaps use a CancellationToken
in case the execution needs to be stop at some point. 可以使用
CancellationToken
代替while(true)
,以防执行需要在某个时刻停止。 Task.Delay()
supports this as well. Task.Delay()
支持此功能。
This are all solutions for a Console application, though. 不过,这些都是控制台应用程序的所有解决方案。 If running as a service, the service host will make sure your program keeps executing after starting, so you can just return.
如果作为服务运行,则服务主机将确保您的程序在启动后继续执行,因此您可以返回。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.