Использую библиотеку MailKit. Вот код
currentOperationTioken = new CancellationTokenSource();
client = new ImapClient();
client.Connected += Client_Connected;
client.Authenticated += Client_Authenticated;
client.Connect("imap", 993, true);
client.Authenticate("login", "pass");
inbox = client.Inbox.GetSubfolder("some");
inbox.Open(FolderAccess.ReadOnly);
inbox.CountChanged += Inbox_CountChanged;
client.IdleAsync(currentOperationTioken.Token);
lock (client.SyncRoot)
{
foreach (var uid in inbox.Search(SearchQuery.NotSeen))
{
//var message = inbox.GetMessage(uid);
Console.WriteLine(inbox.GetMessage(uid).Subject);
}
Console.WriteLine(inbox.Count);
}
На строке foreach (var uid in inbox.Search(SearchQuery.NotSeen))
ловлю вот такую ошибку :"The ImapClient is currently busy processing a command in another thread. Lock the SyncRoot property to properly synchronize your threads."
С потоками у меня все плохо, помогите разобраться пожалуйста как правильно сделать. Код, который находится в lock
будет отрабатывать в событии Inbox_CountChanged
, если я правильно понимаю, то под капотом IdleAsync
, какой то вечный цикл, потому что у объекта client
есть метод Idle
, после которого код останавливается на мониторинге директории(Методом тыка проверял). Уже думаю над вариантов делать два объекта ImapClient
, один для мониторинга директории на новые сообщения, второй для вычитки это директории, но мне это не нравится.
Пробовал сделать с использованием await
. Выполнение останавливается на строке вызова асинхронного метода(Я так думаю), так как дальше ничего не происходит.
private async static void connectImap()
{
currentOperationTioken = new CancellationTokenSource();
CancellationTokenSource currentOperationTioken1 = new CancellationTokenSource();
client.Connected += Client_Connected;
client.Authenticated += Client_Authenticated;
client.Connect("imap", 993, true);
client.Authenticate("login", "pass");
inbox = client.Inbox.GetSubfolder("some");
inbox.Open(FolderAccess.ReadOnly);
inbox.CountChanged += Inbox_CountChanged;
await client.IdleAsync(currentOperationTioken.Token);
lock (client.SyncRoot)
{
foreach (var uid in inbox.Search(SearchQuery.NotSeen))
{
//var message = inbox.GetMessage(uid);
Console.WriteLine(inbox.GetMessage(uid).Subject);
}
Console.WriteLine(inbox.Count);
}
}
Причина ошибки
Метод IdleAsync асинхронный, возвращающий Task.
Не дожидаясь выполнения асинхронной операции, вы пытаетесь использовать синхронную версию метода, используя специальное свойство для синхронизации синхронных операций SyncRoot. Но ваша предыдущая асинхронная операция еще не завершилась, другой поток работает с клиентом. Соответственно и вы и получаете данную ошибку.
Как правильно работать с клиентом?
Согласно документации, метод IdleAsync переводит клиента в состояние IDLE(паузы). Чтобы клиента вывести из состояния IDLE(паузы) и завершить асинхронную операцию, вам необходимо для токена currentOperationTioken
, который вы передали в качестве параметра функции, вызвать метод Сancel
. Тогда ваша асинхронная задача "начнет завершаться".
Поэтому у вас должен быть следующий алгоритм работы:
1. Вызываете асинхронный метод IdleAsync
(без await), сохраняя в переменной возвращаемый Task
2. Когда вам необходимо что-то прочитать, сделать, обработать то, что получили от сервера, вы вызываете Cancel
для токена, который вы передали в функцию в качестве параметра.
3. Вызываете await
для Task
, который вернул вам метод IdleAsync
, чтобы ТОЧНО дождаться завершения асинхронной операции .
4. Выполняете обработку данных.
5. После всей обработки, снова вызываете метод IdleAsync
, переводя клиента в состояние IDLE, чтобы продолжить получать события от сервера.
И так далее.
Стоит еще отметить, что отмененный токен нельзя использовать повторно. Необходимо создавать все время новый токен с помощью классаCancellationTokenSource для каждого вызова IdleAsync
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Прочитал на хабре, что можно уменьшить время компиляции, за счет ключа параллельной компиляции /MPВ настройках не вижу таких пунктов
Не могу разобраться с проблемой десериализации колекции объектов
Нужно что-нибудь не сложное по типу Lazarus
Задача стоит в том чтобы текущий пункт меню подсвечивая, но что-то не работает