Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Idle problen when fetch messages #749

Closed
pfuentes1402 opened this issue Sep 5, 2018 · 10 comments
Closed

Idle problen when fetch messages #749

pfuentes1402 opened this issue Sep 5, 2018 · 10 comments
Labels
question A question about how to do something

Comments

@pfuentes1402
Copy link

I am running the MailKit / samples / ImapIdle / project and I added a line of code in the CountChanged event to get the messages from the mail server in this way: var uids = folder.Search (SearchQuery.NotSeen); but when he executes that line he throws the next exception
The ImapClient is currently busy processing a command in another thread. Lock the SyncRoot property to properly synchronize your threads.

try lock SyncRoot in this way:
lock (folder.SyncRoot)
{
var uids = folder.Search (SearchQuery.NotSeen);
}

but keep throwing this exception. How can I solve that? Thanks in advance.

PS: I am using MailKit 2.0.1

@jstedfast jstedfast added the question A question about how to do something label Sep 6, 2018
@jstedfast
Copy link
Owner

You cannot query the ImapClient or an ImapFolder from within event callbacks. You have to just update your local state so that when the current command completes, you can then use that state info to decide what the next command(s) should be.

The reason for this is that MailKit emits events immediately as they are sent across the wire from the IMAP server and does not wait until the current command has finished being processed.

@Havret
Copy link

Havret commented Nov 20, 2018

Is there any way to know when current command finish processing?

@jstedfast
Copy link
Owner

Yea, when the method returns it means it's done processing.

@Havret
Copy link

Havret commented Nov 20, 2018

But I am thinking about event handler scenario.

_client.Inbox.CountChanged += (sender, args) =>
{
    // some command is being processed in the meantime
};

@jstedfast
Copy link
Owner

jstedfast commented Nov 20, 2018

This is what you can do:

bool countChanged = false;
client.Inbox.CountChanged += (sender, args) => { countChanged = true; };
client.Inbox.DoSomething ();
if (countChanged) {
    // now fetch the new messages
}

@jstedfast
Copy link
Owner

Here's another option:

Task task;

client.Inbox.CountChanged += (sender, args) => {
    task = task.ContinueWith (...);
};
task = client.Inbox.DoSomethingAsync ();

@Havret
Copy link

Havret commented Nov 20, 2018

The problem was with coming back from idle when I received new message. Now I am doing sth like this -->

_client.IdleAsync(_cancellationTokenSource.Token).ContinueWith(x =>
{
    self.Tell(new IdleStopped());
});

@jstedfast
Copy link
Owner

If you are just talking about breaking out of idle, you could do this:

var done = new CancellationTokenSource (timeSpan);

client.Inbox.CountChanged += (sender, args) => { done.Cancel (); };
await client.IdleAsync (done.Token, cancel.Token);

@jstedfast
Copy link
Owner

Most mail client software that supports IDLE uses multiple connections.

They'll use 1 connection for IDLE and another connection to actually fetch the messages and such.

That allows them to do something like this:

idleClient.CountChanged += (sender, args) => { otherClient.Fetch (...); };
await idleClient.IdleAsync (doneToken, cancelToken);

@rklec
Copy link
Contributor

rklec commented Mar 5, 2024

For future reference, see also this discussion: #1723

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question A question about how to do something
Projects
None yet
Development

No branches or pull requests

4 participants