From: Rolf Bjarne Kvinge Date: Wed, 25 Nov 2015 13:03:56 +0000 (+0100) Subject: [System] Fix SmtpClientTest.Deliver_Async to not require main thread processing. X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=mono.git;a=commitdiff_plain;h=3c9209bb4296673956aea216c0cbeade28eb9868 [System] Fix SmtpClientTest.Deliver_Async to not require main thread processing. --- diff --git a/mcs/class/System/Test/System.Net.Mail/SmtpClientTest.cs b/mcs/class/System/Test/System.Net.Mail/SmtpClientTest.cs index 8bba21c0bde..8fa752a4476 100644 --- a/mcs/class/System/Test/System.Net.Mail/SmtpClientTest.cs +++ b/mcs/class/System/Test/System.Net.Mail/SmtpClientTest.cs @@ -392,21 +392,48 @@ namespace MonoTests.System.Net.Mail [Test] public void Deliver_Async () { - var server = new SmtpServer (); - var client = new SmtpClient ("localhost", server.EndPoint.Port); - var msg = new MailMessage ("foo@example.com", "bar@example.com", "hello", "howdydoo\r\n"); - - Thread t = new Thread (server.Run); - t.Start (); - var task = client.SendMailAsync (msg); - t.Join (); + // SmtpClient uses BackgroundWorker and listens for the RunWorkerCompleted + // to mark an async task as completed. The problem is that BackgroundWorker uses + // System.ComponentModel.AsyncOperationManager to get the synchronization + // context, and in monotouch that returns by default a synchronization + // context for the main thread. Since tests are also run on the main thread, + // we'll block the main thread while waiting for the async send to complete, + // while the async completion is waiting for the main thread to process it. + // So instead use a SynchronizationContext that uses the threadpool instead + // of the main thread. + var existing_context = global::System.ComponentModel.AsyncOperationManager.SynchronizationContext; + global::System.ComponentModel.AsyncOperationManager.SynchronizationContext = new ThreadPoolSynchronizationContext (); + try { + var server = new SmtpServer (); + var client = new SmtpClient ("localhost", server.EndPoint.Port); + var msg = new MailMessage ("foo@example.com", "bar@example.com", "hello", "howdydoo\r\n"); + + Thread t = new Thread (server.Run); + t.Start (); + var task = client.SendMailAsync (msg); + t.Join (); + + Assert.AreEqual ("", server.mail_from); + Assert.AreEqual ("", server.rcpt_to); + + Assert.IsTrue (task.Wait (1000)); + Assert.IsTrue (task.IsCompleted, "task"); + } finally { + global::System.ComponentModel.AsyncOperationManager.SynchronizationContext = existing_context; + } + } - Assert.AreEqual ("", server.mail_from); - Assert.AreEqual ("", server.rcpt_to); + internal class ThreadPoolSynchronizationContext : SynchronizationContext + { + public override void Post (SendOrPostCallback d, object state) + { + ThreadPool.QueueUserWorkItem ((v) => d (state)); + } - Assert.IsTrue (task.Wait (1000)); - Assert.IsTrue (task.IsCompleted, "task"); + public override void Send (SendOrPostCallback d, object state) + { + d (state); + } } - } }