AMQP.Net Lite uses an asynchronous connection "pump" (a continuous loop that processes I/O) to handle sending and receiving. It is critical that your application does not block this pump, as doing so prevents the library from processing I/O, which typically leads to deadlocks, application hangs, or timeout errors.
There are two primary ways to accidentally block the pump:
- Performing blocking operations in a callback: If you use a callback (e.g., in a
Send method), do not perform long-running or blocking work (like Thread.Sleep) directly inside it. Instead, schedule the work asynchronously. - Blocking in an async continuation: If an
await operation completes and its continuation runs synchronously on the same thread used by the pump, blocking that thread will halt all I/O. To prevent this, ensure continuations do not run on threads performing blocking work, or wrap async operations using a TaskCompletionSource with TaskCreationOptions.RunContinuationsAsynchronously.
Important: Avoid mixing the synchronous API with the asynchronous API on the same thread. For example, calling a synchronous .Send() immediately after an await .SendAsync() can cause the synchronous call to timeout because the pump cannot process the required acknowledgements.
// BAD: Blocking inside a callback
SenderLink sender = new SenderLink(session, "sender", "q1");
sender.Send(
new Message("test"),
(m, o, s) => Thread.Sleep(120000), // This blocks the pump
sender);
// BAD: Mixing sync and async in a way that blocks the pump
SenderLink sender = new SenderLink(session, "sender", "q1");
await sender.SendAsync(new Message("m1"));
sender.Send(new Message("m2")); // This will likely timeout