使用 MailKit 的线程安全 GetFolder

Thread safe GetFolder using MailKit

我在使用多线程使用 MailKit 的 GetFolder 函数时遇到问题。 情况是他们我是 运行 一个将移动我的电子邮件的线程(除其他功能外,它确实使用 GetFolder 查找我的源文件夹和目标文件夹以便电子邮件移动),另一个线程将搜索对于一封电子邮件,而第一个是 运行(第二个线程也是你的 GetFolder 函数)。

大多数时候我收到 InvalidOperationException 告诉我 "The ImapClient is currently busy processing a command."

我怎样才能确保这不会发生??我尝试将我所有的 GetFolder 和其他 MailKit 操作更改为异步,并等待任务完成,但没有任何运气或多或少同时执行此操作。

我为两个线程使用相同的 ImapClient。

正如上面评论中提到的,使用队列可能是正确的解决方案。

不过,我想我会发表评论,为任何想在多线程环境中使用 MailKit 的人指出一个重要的难题,即 ImapClientImapFolder 有一个共享SyncRoot 属性(ImapClient.SyncRootImapFolder.SyncRoot)用于在多个线程之间同步使用单个 IMAP 连接。

所有 *Async() 方法都会为您锁定 SyncRoot,但非异步方法不会。

在 IMAP 中使用多线程时要记住的另一件事是 IMAP 的工作方式是在任何给定时间只允许打开 1 个文件夹,这意味着如果您有 1 个线程尝试移动邮件从 WorkMailWorkMailArchive 和另一个试图搜索 PersonalMail 的线程,您可能 运行 进入文件夹选择状态竞争条件,这就是为什么使用队列可能更好想法。

编辑: 从 2.0 版本开始,Async 方法不再为您进行任何锁定。你必须自己做。这是因为所有 Async 方法现在都是真正的异步,而不是围绕同步 API.

的 Task.Run() 包装器