diff --git a/src/csharp/GrpcApiTests/MathClientServerTests.cs b/src/csharp/GrpcApiTests/MathClientServerTests.cs
index f5c74573debcd8155dd35283e93f84d57e748232..bb3f75d4acb0e57bd4afe228f91c9477a4c62980 100644
--- a/src/csharp/GrpcApiTests/MathClientServerTests.cs
+++ b/src/csharp/GrpcApiTests/MathClientServerTests.cs
@@ -46,7 +46,7 @@ namespace math.Tests
     /// </summary>
     public class MathClientServerTest
     {
-        string serverAddr = "localhost:" + PortPicker.PickUnusedPort();
+        string host = "localhost";
         Server server;
         Channel channel;
         MathGrpc.IMathServiceClient client;
@@ -54,11 +54,13 @@ namespace math.Tests
         [TestFixtureSetUp]
         public void Init()
         {
+            GrpcEnvironment.Initialize();
+
             server = new Server();
             server.AddServiceDefinition(MathGrpc.BindService(new MathServiceImpl()));
-            server.AddPort(serverAddr);
+            int port = server.AddPort(host + ":0");
             server.Start();
-            channel = new Channel(serverAddr);
+            channel = new Channel(host + ":" + port);
             client = MathGrpc.NewStub(channel);
         }
 
diff --git a/src/csharp/GrpcCore/Channel.cs b/src/csharp/GrpcCore/Channel.cs
index 242e2b621abbd7c18cee44b75f21a8e26644aaa5..cd4f151f49fe33cc5754ea66761b68e260f3e87c 100644
--- a/src/csharp/GrpcCore/Channel.cs
+++ b/src/csharp/GrpcCore/Channel.cs
@@ -41,13 +41,6 @@ namespace Google.GRPC.Core
 {
 	public class Channel : IDisposable
 	{
-        /// <summary>
-        /// Make sure GPRC environment is initialized before any channels get used.
-        /// </summary>
-        static Channel() {
-            GrpcEnvironment.EnsureInitialized();
-        }
-       
         readonly ChannelSafeHandle handle;
         readonly String target;
 
diff --git a/src/csharp/GrpcCore/GrpcCore.csproj b/src/csharp/GrpcCore/GrpcCore.csproj
index 95df89091737dbbb5f264fb127e24da917ca9054..34b9f6dfb82ff66d945488cd68b465b949877ded 100644
--- a/src/csharp/GrpcCore/GrpcCore.csproj
+++ b/src/csharp/GrpcCore/GrpcCore.csproj
@@ -61,7 +61,6 @@
     <Compile Include="Marshaller.cs" />
     <Compile Include="ServerServiceDefinition.cs" />
     <Compile Include="Utils\RecordingObserver.cs" />
-    <Compile Include="Utils\PortPicker.cs" />
     <Compile Include="Utils\RecordingQueue.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
diff --git a/src/csharp/GrpcCore/GrpcEnvironment.cs b/src/csharp/GrpcCore/GrpcEnvironment.cs
index 2febb56d89080d4d58be7a55aaf0adb45e9c9d14..ee1168621d01b1d143de1eb51f2025c35e276da2 100644
--- a/src/csharp/GrpcCore/GrpcEnvironment.cs
+++ b/src/csharp/GrpcCore/GrpcEnvironment.cs
@@ -38,11 +38,9 @@ using System.Runtime.InteropServices;
 namespace Google.GRPC.Core
 {
     /// <summary>
-    /// Encapsulates initialization and shutdown of GRPC C core library.
-    /// You should not need to initialize it manually, as static constructors
-    /// should load the library when needed.
+    /// Encapsulates initialization and shutdown of gRPC library.
     /// </summary>
-    public static class GrpcEnvironment
+    public class GrpcEnvironment
     {
         const int THREAD_POOL_SIZE = 1;
 
@@ -53,21 +51,24 @@ namespace Google.GRPC.Core
         static extern void grpcsharp_shutdown();
 
         static object staticLock = new object();
-        static bool initCalled = false;
-        static bool shutdownCalled = false;
-
-        static GrpcThreadPool threadPool = new GrpcThreadPool(THREAD_POOL_SIZE);
+        static volatile GrpcEnvironment instance;
+       
+        readonly GrpcThreadPool threadPool;
+        bool isClosed;
 
         /// <summary>
-        /// Makes sure GRPC environment is initialized.
+        /// Makes sure GRPC environment is initialized. Subsequent invocations don't have any
+        /// effect unless you call Shutdown first.
+        /// Although normal use cases assume you will call this just once in your application's
+        /// lifetime (and call Shutdown once you're done), for the sake of easier testing it's 
+        /// allowed to initialize the environment again after it has been successfully shutdown.
         /// </summary>
-        public static void EnsureInitialized() {
+        public static void Initialize() {
             lock(staticLock)
             {
-                if (!initCalled)
+                if (instance == null)
                 {
-                    initCalled = true;
-                    GrpcInit();       
+                    instance = new GrpcEnvironment();
                 }
             }
         }
@@ -80,45 +81,55 @@ namespace Google.GRPC.Core
         {
             lock(staticLock)
             {
-                if (initCalled && !shutdownCalled)
+                if (instance != null)
                 {
-                    shutdownCalled = true;
-                    GrpcShutdown();
+                    instance.Close();
+                    instance = null;
                 }
             }
+        }
 
+        internal static GrpcThreadPool ThreadPool
+        {
+            get
+            {
+                var inst = instance;
+                if (inst == null)
+                {
+                    throw new InvalidOperationException("GRPC environment not initialized");
+                }
+                return inst.threadPool;
+            }
         }
 
         /// <summary>
-        /// Initializes GRPC C Core library.
+        /// Creates gRPC environment.
         /// </summary>
-        private static void GrpcInit()
+        private GrpcEnvironment()
         {
             grpcsharp_init();
+            threadPool = new GrpcThreadPool(THREAD_POOL_SIZE);
             threadPool.Start();
             // TODO: use proper logging here
             Console.WriteLine("GRPC initialized.");
         }
 
         /// <summary>
-        /// Shutdown GRPC C Core library.
+        /// Shuts down this environment.
         /// </summary>
-        private static void GrpcShutdown()
+        private void Close()
         {
+            if (isClosed)
+            {
+                throw new InvalidOperationException("Close has already been called");
+            }
             threadPool.Stop();
             grpcsharp_shutdown();
+            isClosed = true;
 
             // TODO: use proper logging here
             Console.WriteLine("GRPC shutdown.");
         }
-
-        internal static GrpcThreadPool ThreadPool
-        {
-            get
-            {
-                return threadPool;
-            }
-        }
     }
 }
 
diff --git a/src/csharp/GrpcCore/Server.cs b/src/csharp/GrpcCore/Server.cs
index ef06c0a6a3b7efeeb3d73d92d3491b6d8a9adf3b..62ffa70b713b17383b014d1e624e7e270739ffa1 100644
--- a/src/csharp/GrpcCore/Server.cs
+++ b/src/csharp/GrpcCore/Server.cs
@@ -59,10 +59,6 @@ namespace Google.GRPC.Core
 
         readonly TaskCompletionSource<object> shutdownTcs = new TaskCompletionSource<object>();
 
-        static Server() {
-            GrpcEnvironment.EnsureInitialized();
-        }
-
         public Server()
         {
             // TODO: what is the tag for server shutdown?
diff --git a/src/csharp/GrpcCore/Utils/PortPicker.cs b/src/csharp/GrpcCore/Utils/PortPicker.cs
deleted file mode 100644
index 7c83bf3886df21c81d39ef6a2b0998fecc6b5b9b..0000000000000000000000000000000000000000
--- a/src/csharp/GrpcCore/Utils/PortPicker.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using System;
-using System.Net;
-using System.Net.Sockets;
-
-namespace Google.GRPC.Core.Utils
-{
-    public class PortPicker
-    {
-        static Random random = new Random();
-
-        // TODO: cleanup this code a bit
-        public static int PickUnusedPort()
-        {
-            int port;
-            do
-            {
-                port = random.Next(2000, 50000);
-
-            } while(!IsPortAvailable(port));
-            return port;
-        }
-
-        // TODO: cleanup this code a bit
-        public static bool IsPortAvailable(int port)
-        {
-            bool available = true;
-
-            TcpListener server = null;
-            try
-            {
-                IPAddress ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
-                server = new TcpListener(ipAddress, port);
-                server.Start();
-            }
-            catch (Exception ex)
-            {
-                available = false;
-            }
-            finally
-            {
-                if (server != null)
-                {
-                    server.Stop();
-                }
-            }
-            return available;
-        }
-    }
-}
-
diff --git a/src/csharp/GrpcCore/Utils/RecordingQueue.cs b/src/csharp/GrpcCore/Utils/RecordingQueue.cs
index 5a91852c8cfe6c681cc3a17e80a0ccc11cc00470..d73fc0fc78599bef7e8180683896c4dd0889b44e 100644
--- a/src/csharp/GrpcCore/Utils/RecordingQueue.cs
+++ b/src/csharp/GrpcCore/Utils/RecordingQueue.cs
@@ -38,6 +38,7 @@ using System.Collections.Concurrent;
 
 namespace Google.GRPC.Core.Utils
 {
+    // TODO: replace this by something that implements IAsyncEnumerator.
     /// <summary>
     /// Observer that allows us to await incoming messages one-by-one.
     /// The implementation is not ideal and class will be probably replaced 
diff --git a/src/csharp/GrpcCoreTests/ClientServerTest.cs b/src/csharp/GrpcCoreTests/ClientServerTest.cs
index 1cfb6da0faa1dfef792c5629c4e91881b7f92ffd..1472db6e07e6ea47331eb43e0c90afdd15e92c3d 100644
--- a/src/csharp/GrpcCoreTests/ClientServerTest.cs
+++ b/src/csharp/GrpcCoreTests/ClientServerTest.cs
@@ -43,7 +43,7 @@ namespace Google.GRPC.Core.Tests
 {
     public class ClientServerTest
     {
-        string serverAddr = "localhost:" + PortPicker.PickUnusedPort();
+        string host = "localhost";
 
         Method<string, string> unaryEchoStringMethod = new Method<string, string>(
             MethodType.Unary,
@@ -54,15 +54,17 @@ namespace Google.GRPC.Core.Tests
         [Test]
         public void EmptyCall()
         {
+            GrpcEnvironment.Initialize();
+
             Server server = new Server();
             server.AddServiceDefinition(
                 ServerServiceDefinition.CreateBuilder("someService")
                     .AddMethod(unaryEchoStringMethod, HandleUnaryEchoString).Build());
 
-            server.AddPort(serverAddr);
+            int port = server.AddPort(host + ":0");
             server.Start();
 
-            using (Channel channel = new Channel(serverAddr))
+            using (Channel channel = new Channel(host + ":" + port))
             {
                 var call = new Call<string, string>(unaryEchoStringMethod, channel);
 
diff --git a/src/csharp/GrpcCoreTests/GrpcEnvironmentTest.cs b/src/csharp/GrpcCoreTests/GrpcEnvironmentTest.cs
index 781d1fc1092c3fddcd70747ee50101065b45cad6..1bc6cce401770a9d4fdea09e76e426dfdad36b9c 100644
--- a/src/csharp/GrpcCoreTests/GrpcEnvironmentTest.cs
+++ b/src/csharp/GrpcCoreTests/GrpcEnvironmentTest.cs
@@ -42,10 +42,30 @@ namespace Google.GRPC.Core.Tests
     {
         [Test]
         public void InitializeAndShutdownGrpcEnvironment() {
-            GrpcEnvironment.EnsureInitialized();
-            Thread.Sleep(500);
+            GrpcEnvironment.Initialize();
             Assert.IsNotNull(GrpcEnvironment.ThreadPool.CompletionQueue);
             GrpcEnvironment.Shutdown();
         }
+
+        [Test]
+        public void SubsequentInvocations() {
+            GrpcEnvironment.Initialize();
+            GrpcEnvironment.Initialize();
+            GrpcEnvironment.Shutdown();
+            GrpcEnvironment.Shutdown();
+        }
+
+        [Test]
+        public void InitializeAfterShutdown() {
+            GrpcEnvironment.Initialize();
+            var tp1 = GrpcEnvironment.ThreadPool;
+            GrpcEnvironment.Shutdown();
+
+            GrpcEnvironment.Initialize();
+            var tp2 = GrpcEnvironment.ThreadPool;
+            GrpcEnvironment.Shutdown();
+
+            Assert.IsFalse(Object.ReferenceEquals(tp1, tp2));
+        }
     }
 }
diff --git a/src/csharp/GrpcCoreTests/ServerTest.cs b/src/csharp/GrpcCoreTests/ServerTest.cs
index d5fd3aab4608f7ddc08b0b4df3e32ee83dead245..1c70a3d6c4421d925fcd5af89d436c0c61e6cfae 100644
--- a/src/csharp/GrpcCoreTests/ServerTest.cs
+++ b/src/csharp/GrpcCoreTests/ServerTest.cs
@@ -42,10 +42,12 @@ namespace Google.GRPC.Core.Tests
     public class ServerTest
     {
         [Test]
-        public void StartAndShutdownServer() {
+        public void StartAndShutdownServer()
+        {
+            GrpcEnvironment.Initialize();
 
             Server server = new Server();
-            server.AddPort("localhost:" + PortPicker.PickUnusedPort());
+            int port = server.AddPort("localhost:0");
             server.Start();
             server.ShutdownAsync().Wait();
 
diff --git a/src/csharp/InteropClient/Client.cs b/src/csharp/InteropClient/Client.cs
index 86845cd76eee768f7d75141d60c22cbe65c32995..fcc6a572e401b4959dbbc4127bcd671f5ac53713 100644
--- a/src/csharp/InteropClient/Client.cs
+++ b/src/csharp/InteropClient/Client.cs
@@ -93,6 +93,8 @@ namespace Google.GRPC.Interop
 
         private void Run()
         {
+            GrpcEnvironment.Initialize();
+
             string addr = string.Format("{0}:{1}", options.serverHost, options.serverPort);
             using (Channel channel = new Channel(addr))
             {
diff --git a/src/csharp/MathClient/MathClient.cs b/src/csharp/MathClient/MathClient.cs
index a740c0ac49f676692624866298b404b4c056b7c9..a54c8e3809931da11862805c74f39ee5a3306f65 100644
--- a/src/csharp/MathClient/MathClient.cs
+++ b/src/csharp/MathClient/MathClient.cs
@@ -42,6 +42,8 @@ namespace math
     {
 		public static void Main (string[] args)
 		{
+            GrpcEnvironment.Initialize();
+
 			using (Channel channel = new Channel("127.0.0.1:23456"))
 			{
 				MathGrpc.IMathServiceClient stub = new MathGrpc.MathServiceClientStub(channel);