   (process-send-eof (merlin-get-process))
   (ignore-errors (delete-process (merlin-get-process)))
   (kill-buffer (merlin-get-process-buffer-name))
+  (with-current-buffer (merlin-get-process-buffer-name)
+    (tq-close merlin--queue))
 )
-(defun merlin-send-command (name args)
-  "Send a command to merlin. Return the result."
+(defun merlin-wait-for-answer ()
+  "Waits for merlin to answer."
+  (with-current-buffer (merlin-get-process-buffer-name)
+      (while (not merlin-ready)
+        (accept-process-output (merlin-get-process) 0.1 nil nil))
+      merlin-result))
+(defun merlin-send-command-async (command args callback-if-success &optional callback-if-exn)
+  "Send a command to merlin. Give the result to callback-if-success. If merlin reported an error and if
+CALLBACK-IF-EXN is non-nil, call the function with the error message otherwise print a generic error message."
   (let ((string
 	 (concat 
-	  (json-encode (if args (append (list name) args) (list name)))
+	  (json-encode (if args (append (list command) args) (list command)))
 	  "\n"))
         (name (buffer-name)))
-    (process-send-string (merlin-get-process) string)
-    (setq merlin-result nil)
     (if merlin-debug (merlin-debug (format "Sending:\n%s\n---\n" string)))
     (with-current-buffer (merlin-get-process-buffer-name)
       (setq merlin-process-last-user name)
-      (when (merlin-wait-for-answer)
-          merlin-result))))
-
+      (tq-enqueue merlin--queue string "\n"
+                  (cons callback-if-success (cons callback-if-exn command))
+                  #'(lambda (closure answer)
+                      (setq merlin-ready t)
+                      (let ((a (ignore-errors (json-read-from-string answer))))
+                        (if a
+                            (progn
+                              (if merlin-debug
+                                  (merlin-debug (format "Received:\n%s\n----\n" answer)))
+                              (if (string-equal (elt a 0) "return")
+                                  (funcall (car closure) (elt a 1))
+                                (progn
+                                  (if (functionp (cadr closure))
+                                      (funcall (cadr closure) (elt a 1))
+                                    (message "Command %s failed with error %s" (cddr closure) (elt a 1))))))
+                          (message "Invalid answer received from merlin.")))))
+      nil)))
+
+(defun merlin-send-command (command args)
+  "Send a command to merlin and returns the result"
+  (with-current-buffer (merlin-get-process-buffer-name)
+    (setq merlin-result nil)
+    (setq merlin-ready nil))
+  (merlin-send-command-async command args #'(lambda (data) (setq merlin-ready t)
+                                              (setq merlin-result data)))
+  (merlin-wait-for-answer))
 
 (defun merlin-is-long (s)
   "Return true if its parameter is long, ie. contains a new line."
   (string-match "sig" s))
 ;; SPECIAL CASE OF COMMANDS
-(defun merlin-get-return-field (data)
-  "Return the actual data of a response or nil if there was an error."
-  (if (string-equal (elt data 0) "return")
-      (elt data 1)
-    nil))
-		    
 (defun merlin-rewind ()
   "Rewind the knowledge of merlin of the current buffer to zero."
   (interactive)

  "Load the .merlin file corresponding to the current file."
  (interactive)
  (merlin-rewind)
  (let ((r (merlin-get-return-field (merlin-send-command "project" (list "find" (buffer-file-name))))))
    (if (and r (listp r))
        (setq merlin--project-file (car r)))))


    (forward-line 1)
    (while (and (not end-p) (< (point) (point-max)))
      (if (equal ;; this is not tautological since value is never nil
           (merlin-tell-piece "end" temp-point (point))
           t)
          (progn
            (setq end-p t))
