MailClient reconnect problem (another operation is pending)

0 votes
asked Mar 6, 2015 by dirk (530 points)

Hello,

I have a problem when I try to reconnect my mail client. I made it like this:

mailClient.disconnect();

mailClient.connect();

..because I haven't found any "reconnect"-function. But I get the error "Another operation is pending", although I am working with locks for my threads.

I checked the state of the client, and it keeps being in "Reading"-state. Is there any way I can change the state programmatically?

Any other ideas about the reason for the exception or different approach to get the reconnect done?

Thanks,
d.rk

Applies to: Rebex Secure Mail

1 Answer

+1 vote
answered Mar 6, 2015 by Lukas Pokorny (114,150 points)

A communication log produced by mailClient.LogWriter (see http://www.rebex.net/kb/logging/default.aspx for details) might make it possible to tell what is going on.

However, Disconnect initiates a graceful disconnect which is not going to work if the connection is already unusable when called. To 'reconnect', the recommended solution is simply to dispose the object (call Dispose method) and create a new one. Unlike Disconnect, this should never fail.

commented Mar 11, 2015 by dirk (530 points)
Hello Lukas,

thanks for your reply.
I managed to get it working, but with some obstacles along the path.
When I changed to Dispose() I got another exception in the callback method of my BeginCheckForUpdates method (which got called right after the Dispose call).
Thus, I had to add another check that EndCheckForUpdates gets only called when clientImap state is ImapState.Ready (the callback method was entered with ImapState.Disposed).

p.s.: The log for disconnect only shows these relevant lines (level: error) when the exception occurs:
2015-03-11 11:50:49.660 Opening log file.
2015-03-11 11:50:49.660 Using FileLogWriter version 2.0.5207.1.
2015-03-11 11:51:31.720 ERROR Imap(2)[8] Info: Another operation is pending.

Is there a way to work without the check?
commented Mar 12, 2015 by Lukas Pokorny (114,150 points)
Hello Dirk, thanks for the log and other information.

The `Disconnect` method didn't work because the `Imap` object does not support multiple simultaneous operations. If you are running one method (such as `CheckForUpdates` or its asynchronous variant), you can't call `Disconnect` (or another method) before it ends. The `Dispose` method is an exception to this (it can be called at any time and it terminates any currently running operation).

However, without access to any part of your code, it's difficult to offer advice on it. The general recommendation is to structure your code in such a way that you never call multiple `Imap` methods simultaneously. If you are running `CheckForUpdates` and need to disconnect gracefully, it's recommended to use `Abort` method to end the `CheckForUpdates` call and call `Disconnect` right after `EndCheckForUpdates`.

Calling `BeginCheckForUpdates` on a disposed object doesn't make much sense and it should always fail in that state. The recommendation is to call it for the first time after the `Imap` object has been connected and authenticated and there is no outstanding work to perform. Then, when the background operation ends successfully, call `BeginCheckForUpdates` again (or do something else if there is anything that needs to be done).

Finally, please note that Begin/End asynchronous pattern, which was introduced in 2001 with .NET 1.0, is now considered outdated. We recommend using the Task-based asynchronous pattern instead, preferably with .NET 4.5's async/await keywords which greatly simplify asynchronous programming. Please check out http://www.rebex.net/secure-mail.net/features/asynchronous-operations.aspx#task-based for more information.
...