diff --git a/GPipe-GLFW.cabal b/GPipe-GLFW.cabal
--- a/GPipe-GLFW.cabal
+++ b/GPipe-GLFW.cabal
@@ -1,5 +1,5 @@
 name:                GPipe-GLFW
-version:             1.0
+version:             1.1
 cabal-version:       >=1.10
 build-type:          Simple
 author:              Patrick Redmond
@@ -22,7 +22,7 @@
                        base >=4.7 && <4.9,
                        transformers >= 0.3 && < 0.5,
                        GLFW-b >=1.4 && <1.5,
-                       GPipe >=2.0 && <2.1
+                       GPipe >=2.1 && <2.2
   ghc-options:         -Wall
   default-language:    Haskell2010
   exposed-modules:     Graphics.GPipe.Context.GLFW
@@ -40,4 +40,4 @@
   type:     git
   location: git@github.com:plredmond/GPipe-GLFW.git
   subdir:   GPipe-GLFW
-  tag:      v1.0
+  tag:      v1.1
diff --git a/src/Graphics/GPipe/Context/GLFW.hs b/src/Graphics/GPipe/Context/GLFW.hs
--- a/src/Graphics/GPipe/Context/GLFW.hs
+++ b/src/Graphics/GPipe/Context/GLFW.hs
@@ -7,22 +7,21 @@
 ) where
 
 import qualified Control.Concurrent as C
-import qualified Control.Monad as M
 import qualified Graphics.GPipe.Context.GLFW.Format as Format
 import qualified Graphics.GPipe.Context.GLFW.Resource as Resource
 import qualified Graphics.GPipe.Context.GLFW.Util as Util
-import qualified Graphics.UI.GLFW as GLFW (getCursorPos, getMouseButton, getKey, windowShouldClose, makeContextCurrent, destroyWindow)
+import qualified Graphics.UI.GLFW as GLFW (getCursorPos, getMouseButton, getKey, windowShouldClose, makeContextCurrent, destroyWindow, pollEvents)
 
 import Control.Monad.IO.Class (MonadIO)
-import Data.Maybe (isNothing)
 import Graphics.GPipe.Context (ContextFactory, ContextHandle(..),ContextT,withContextWindow)
-import Graphics.GPipe.Format (ContextFormat)
 import Graphics.UI.GLFW (MouseButtonState(..), MouseButton(..), KeyState(..), Key(..))
-
-type Message = Maybe Request
+import Data.IORef
+import Control.Monad (when)
 
-data Request where
-    ReqExecute :: forall a. IO a -> Maybe (C.MVar a) -> Request
+data Message where
+    ReqShutDown :: C.MVar () -> Message
+    ReqExecuteSync :: forall a. IO a -> C.MVar a -> Message
+    ReqExecuteAsync :: IO () -> Message
 
 ------------------------------------------------------------------------------
 -- Top-level
@@ -31,25 +30,31 @@
 newtype GLFWWindow = GLFWWindow { unGLFWWindow :: Resource.Window }
 
 -- | The context factory which facilitates use of GLFW with GPipe.
+--   This has to be run from the main thread.
 newContext :: ContextFactory c ds GLFWWindow
 newContext fmt = do
     chReply <- C.newEmptyMVar
-    _ <- C.forkOS $ begin chReply fmt
-    C.takeMVar chReply
+    _ <- C.forkOS $ begin chReply
+    msgC <- C.takeMVar chReply
+    h <- createContext msgC Nothing fmt    
+    contextDoAsync h True (return ()) -- First action on render thread: Just make window current
+    return h 
 
 createContext :: C.Chan Message -> Maybe Resource.Window -> ContextFactory c ds GLFWWindow
 createContext msgC share fmt = do
     w <- makeContext share
+    GLFW.makeContextCurrent Nothing
+    alive <- newIORef True -- This will always be used from render thread so no need to synchronize
     return ContextHandle
-        { newSharedContext = contextDoSyncImpl w msgC . createContext msgC (Just w)
+        { newSharedContext = mainthreadDoWhileContextUncurrent msgC w . createContext msgC (Just w) -- Create context on this thread while parent is uncurrent, then make parent current
         , contextDoSync = contextDoSyncImpl w msgC
-        , contextDoAsync = contextDoAsyncImpl w msgC
-        , contextSwap = Util.swapBuffers w -- this thread only
-        , contextFrameBufferSize = Util.getFramebufferSize w -- this thread only
-        , contextDelete = do
-            contextDoSyncImpl w msgC (GLFW.destroyWindow w)
-            -- Shut down thread when outermost shared context is destroyed
-            M.when (isNothing share) $ contextDeleteImpl msgC
+        , contextDoAsync = contextDoAsyncImpl alive w msgC
+        , contextSwap = contextDoSyncImpl w msgC False $ Util.swapBuffers w -- explicitly do it on the render thread to sync properly, GLFW allows this
+        , contextFrameBufferSize = Util.getFramebufferSize w -- Runs on mainthread
+        , contextDelete = case share of
+            Nothing -> do contextDeleteImpl msgC -- This return when render thread is uncurrent and is shutting down (cannot serve any finalizers)
+                          GLFW.destroyWindow w
+            Just parentW  -> mainthreadDoWhileContextUncurrent msgC parentW (writeIORef alive False >> GLFW.destroyWindow w) -- Shared contexts still alive, delete while uncurrent, then make parent win current
         , contextWindow = GLFWWindow w
         }
     where
@@ -58,15 +63,15 @@
         makeContext Nothing = Resource.newContext Nothing hints Nothing
         makeContext (Just s) = Resource.newSharedContext s hints Nothing
 
+
 ------------------------------------------------------------------------------
 -- OpenGL Context thread
 
--- Create and pass back a ContextHandle. Enter loop.
-begin :: C.MVar (ContextHandle GLFWWindow) -> ContextFormat c ds -> IO ()
-begin chReply fmt = do
+-- Create and pass back a channel. Enter loop.
+begin :: C.MVar (C.Chan Message) ->  IO ()
+begin chReply = do
     msgC <- C.newChan
-    handle <- createContext msgC Nothing fmt
-    C.putMVar chReply handle
+    C.putMVar chReply msgC
     loop msgC
 
 -- Handle messages until a stop message is received.
@@ -74,33 +79,57 @@
 loop msgC = do
     msg <- C.readChan msgC
     case msg of
-        Nothing -> return ()
-        Just req -> doRequest req >> loop msgC
-
--- Do what the a request asks.
-doRequest :: Request -> IO ()
-doRequest (ReqExecute action Nothing) = M.void action
-doRequest (ReqExecute action (Just reply)) = action >>= C.putMVar reply
+        ReqShutDown reply -> GLFW.makeContextCurrent Nothing >> C.putMVar reply ()
+        ReqExecuteSync action reply -> action >>= C.putMVar reply >> loop msgC
+        ReqExecuteAsync action -> action >> loop msgC
 
 ------------------------------------------------------------------------------
 -- Application rpc calls
 
 -- Await sychronous concurrent IO from the OpenGL context thread
-contextDoSyncImpl :: Resource.Window -> C.Chan Message -> IO a -> IO a
-contextDoSyncImpl w msgC action = do
+contextDoSyncImpl :: Resource.Window -> C.Chan Message -> Bool -> IO a -> IO a
+contextDoSyncImpl w msgC inwin action = do
     reply <- C.newEmptyMVar
-    C.writeChan msgC . Just $ ReqExecute (GLFW.makeContextCurrent (Just w) >> action) (Just reply)
+    C.writeChan msgC $ ReqExecuteSync (do when inwin (GLFW.makeContextCurrent (Just w))
+                                          action)
+                                      reply
+    GLFW.pollEvents -- Ugly hack, but at least every swapContextBuffers will run this 
     C.takeMVar reply
 
 -- Dispatch asychronous concurrent IO to the OpenGL context thread
-contextDoAsyncImpl :: Resource.Window -> C.Chan Message -> IO () -> IO ()
-contextDoAsyncImpl w msgC action =
-    C.writeChan msgC . Just $ ReqExecute (GLFW.makeContextCurrent (Just w) >> action) Nothing
+contextDoAsyncImpl :: IORef Bool -> Resource.Window -> C.Chan Message -> Bool -> IO () -> IO ()
+contextDoAsyncImpl alive w msgC inwin action =
+    C.writeChan msgC $ ReqExecuteAsync $ if inwin 
+                                            then do -- If needed to be run in this window, then only do it if window still exists
+                                                alive' <- readIORef alive 
+                                                when alive' $ do 
+                                                        GLFW.makeContextCurrent (Just w)
+                                                        action
+                                            else
+                                                action
 
+-- Do action while renderhtread is uncurrent 
+mainthreadDoWhileContextUncurrent :: C.Chan Message -> Resource.Window -> IO a -> IO a
+mainthreadDoWhileContextUncurrent msgC w mainAction = do
+    syncMainWait <- C.newEmptyMVar
+    syncRendWait <- C.newEmptyMVar
+    let m = do GLFW.makeContextCurrent Nothing
+               C.putMVar syncMainWait ()                                                                    
+               C.takeMVar syncRendWait -- Stop other async code from making window current (e.g. finalizers)
+               GLFW.makeContextCurrent (Just w)
+               
+    C.writeChan msgC $ ReqExecuteAsync m 
+    C.takeMVar syncMainWait -- Wait for render thread to make window uncurrent
+    ret <- mainAction
+    C.putMVar syncRendWait () -- Release render thread
+    return ret
+
 -- Request that the OpenGL context thread shut down
 contextDeleteImpl :: C.Chan Message -> IO ()
-contextDeleteImpl msgC =
-    C.writeChan msgC Nothing
+contextDeleteImpl msgC = do
+    syncMainWait <- C.newEmptyMVar
+    C.writeChan msgC $ ReqShutDown syncMainWait
+    C.takeMVar syncMainWait
 
 ------------------------------------------------------------------------------
 -- Exposed window actions
diff --git a/src/Graphics/GPipe/Context/GLFW/Util.hs b/src/Graphics/GPipe/Context/GLFW/Util.hs
--- a/src/Graphics/GPipe/Context/GLFW/Util.hs
+++ b/src/Graphics/GPipe/Context/GLFW/Util.hs
@@ -11,9 +11,9 @@
 -- Util
 
 swapBuffers :: GLFW.Window -> IO ()
-swapBuffers w = GLFW.makeContextCurrent (Just w) >> GLFW.swapBuffers w >> GLFW.pollEvents
+swapBuffers = GLFW.swapBuffers
 
 getFramebufferSize :: GLFW.Window -> IO (Int, Int)
-getFramebufferSize w = GLFW.makeContextCurrent (Just w) >> GLFW.getFramebufferSize w
+getFramebufferSize = GLFW.getFramebufferSize
 
 -- eof
