当收到新电子邮件时,将运行闲置停止方法,并在其中显示Imap客户端当前正在另一个线程中进行处理。我认为是因为闲置命令仍在后台线程中运行? 即使我调用thread.Join()方法,也不会结束。我在这里呆了很长时间,MailKit github上的示例演示仅显示了如何在手动用户输入(例如Console.ReadKey())的帮助下进行处理。 我敢肯定,我缺少一些要点,或者代码有重大缺陷,但是我已经搜索了很多次答案,除了github示例以外,似乎没有任何重要结果
协议记录器,当空闲启动并收到消息后,直到出现异常为止
File "/home/wangxu/pyApp/flaskApp/bin/gunicorn", line 11, in <module>
sys.exit(run())
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/app/wsgiapp.py", line 61, in run
WSGIApplication("%(prog)s [OPTIONS] [APP_MODULE]").run()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/app/base.py", line 223, in run
super(Application, self).run()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/app/base.py", line 72, in run
Arbiter(self).run()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/arbiter.py", line 203, in run
self.manage_workers()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/arbiter.py", line 545, in manage_workers
self.spawn_workers()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/arbiter.py", line 616, in spawn_workers
self.spawn_worker()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker
worker.init_process()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/workers/base.py", line 134, in init_process
self.run()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/workers/sync.py", line 124, in run
self.run_for_one(timeout)
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/workers/sync.py", line 68, in run_for_one
self.accept(listener)
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/workers/sync.py", line 30, in accept
self.handle(listener, client, addr)
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/workers/sync.py", line 135, in handle
self.handle_request(listener, req, client, addr)
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/gunicorn/workers/sync.py", line 176, in handle_request
respiter = self.wsgi(environ, resp.start_response)
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/flask/app.py", line 2328, in __call__
return self.wsgi_app(environ, start_response)
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/flask/app.py", line 2311, in wsgi_app
response = self.full_dispatch_request()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/flask/app.py", line 1832, in full_dispatch_request
rv = self.dispatch_request()
File "/home/wangxu/pyApp/flaskApp/lib/python3.6/site-packages/flask/app.py", line 1818, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/wangxu/pyApp/flaskApp/app.py", line 10, in hello
s = traceback.print_stack()
开始闲置的方法
KStream<String, byte[]> stream = streamsBuilder.stream(topic);
stream.selectKey((k, v) -> {
Map<String, String> headers = this.getHeaders(v);
return ParserService.getFieldValue(headers, "api_message_id");
})
.groupByKey()
.aggregate(() -> new byte[]{}, (aggKey, newValue, aggValue) -> {
byte[] c = new byte[aggValue.length + newValue.length];
System.arraycopy(aggValue, 0, c, 0, aggValue.length);
System.arraycopy(newValue, 0, c, aggValue.length, newValue.length);
return c;
})
.toStream()
.foreach((k, v) -> {
Map<String, String> headers = this.getHeaders(v);
parserService.processGroupedMessage(getHeaders(v));
});
与闲置有关的声明
S: * OK [UIDNEXT 21641] Predicted next UID.
S: * OK [HIGHESTMODSEQ 881089]
S: A00000006 OK [READ-WRITE] INBOX selected. (Success)
C: A00000007 IDLE
S: + idling
S: * 21512 EXISTS
C: DONE
停止闲置方法
IdleClient.Inbox.MessageExpunged += OnMessageExpunged;
IdleClient.Inbox.CountChanged += OnInboxCountChanged;
ImapToken = new CancellationTokenSource();
SetTokenValues(ImapToken.Token);
ImapToken.Token.ThrowIfCancellationRequested();
ImapThreadInfo = Helpers.InBackgroundThread(ImapIdleLoop, UniqueAccountId, true);
空闲循环方法
private (int, Thread) ImapThreadInfo;
private CancellationToken CancellationToken { get; set; }
private CancellationToken DoneToken { get; set; }
private CancellationTokenSource ImapToken { get; set; }
private CancellationTokenSource Timeout { get; set; }
private bool IsCancellationRequested => CancellationToken.IsCancellationRequested || DoneToken.IsCancellationRequested;
private readonly object Mutex = new object();
private void CancelTimeout() {
lock (Mutex) {
Timeout?.Cancel();
}
}
private void SetTimeoutSource(CancellationTokenSource source) {
lock (Mutex) {
Timeout = source;
if (Timeout != null && IsCancellationRequested) {
Timeout.Cancel();
}
}
}
private void SetTokenValues(CancellationToken doneToken, CancellationToken cancellationToken = default) {
CancellationToken = cancellationToken;
DoneToken = doneToken;
doneToken.Register(CancelTimeout);
}
答案 0 :(得分:0)
问题在于您正在等待线程从ImapClient的事件回调中加入,这意味着您正在阻止ImapClient继续运行。
解决方案是:不要这样做。
在IMAP命令处理器仍在处理服务器响应时,会发出MailKit的IMAP事件,因此您不能在这些事件处理程序中的同一ImapClient上调用更多命令。
您需要做的是在程序中实现某种命令队列,然后在CountChanged事件处理程序(或您正在处理的任何处理程序)中,将下一个命令排队,以在当前命令后调用一次完成。
一种简单的方法是将System.Threading.Tasks.Task
保留在事件处理程序可以访问它并可以执行的位置:
task = task.ContinueWith (...);
这是实现命令队列的简单方法。