Index: Enyim.Caching/Enyim.Caching.csproj
===================================================================
--- Enyim.Caching/Enyim.Caching.csproj	(revision 14893)
+++ Enyim.Caching/Enyim.Caching.csproj	(working copy)
@@ -81,6 +81,8 @@
     <Compile Include="Memcached\StoreMode.cs" />
     <Compile Include="Memcached\Operations\StoreOperation.cs" />
     <Compile Include="StatItem.cs" />
+    <Compile Include="Threading\AsyncResult.cs" />
+    <Compile Include="Threading\AsyncResultNoResult.cs" />
     <Compile Include="TigerHash.cs" />
   </ItemGroup>
   <ItemGroup>
Index: Enyim.Caching/MemcachedClient.cs
===================================================================
--- Enyim.Caching/MemcachedClient.cs	(revision 14893)
+++ Enyim.Caching/MemcachedClient.cs	(working copy)
@@ -10,9 +10,17 @@
 using Enyim.Caching.Memcached;
 using Enyim.Configuration;
 using System.Configuration;
+using Enyim.Caching.Threading;
 
 namespace Enyim.Caching
 {
+    internal struct BasicSetParams
+    {
+        public StoreMode mode;
+        public string key;
+        public object value;
+    }
+
 	public sealed class MemcachedClient
 	{
 		public static readonly TimeSpan Infinite = TimeSpan.Zero;
@@ -133,6 +141,37 @@
 			return MemcachedClient.Store(this.pool, (StoreCommand)mode, key, value, 0, MemcachedClient.Infinite, DateTime.MinValue);
 		}
 
+        public IAsyncResult BeginStore(AsyncCallback callback,  StoreMode mode, string key, object value) {
+            BasicSetParams bsp= new BasicSetParams();
+            bsp.key = key;
+            bsp.mode = mode;
+            bsp.value = value;
+
+            AsyncResult<bool> ar = new AsyncResult<bool>(callback, bsp);
+            ThreadPool.QueueUserWorkItem(StoreHelper,ar);
+            return ar;
+        }
+
+        public bool EndStore(IAsyncResult asyncResult) {
+            AsyncResult<bool> ar = (AsyncResult<bool>)asyncResult;
+            return ar.EndInvoke();
+        }
+
+        private void StoreHelper(Object asyncResult) {
+            AsyncResult<bool> ar = (AsyncResult<bool>)asyncResult;
+            BasicSetParams bsp = (BasicSetParams)ar.AsyncState;
+            try
+            {
+                bool result = this.Store(bsp.mode, bsp.key, bsp.value);
+                ar.SetAsCompleted(result, false);
+            }
+            catch (Exception e)
+            {
+                // If operation fails, set the exception
+                ar.SetAsCompleted(e, false);
+            }
+        }
+
 		/// <summary>
 		/// Inserts a range of bytes (usually memory area or serialized data) into the cache with a cache key to reference its location.
 		/// </summary>
Index: Enyim.Caching/Threading/AsyncResult.cs
===================================================================
--- Enyim.Caching/Threading/AsyncResult.cs	(revision 0)
+++ Enyim.Caching/Threading/AsyncResult.cs	(revision 0)
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Enyim.Caching.Threading
+{
+    internal class AsyncResult<TResult> : AsyncResultNoResult
+    {
+        // Field set when operation completes
+        private TResult m_result = default(TResult);
+
+        public AsyncResult(AsyncCallback asyncCallback, Object state)
+            :
+           base(asyncCallback, state) { }
+
+        public void SetAsCompleted(TResult result,
+           Boolean completedSynchronously)
+        {
+            // Save the asynchronous operation's result
+            m_result = result;
+
+            // Tell the base class that the operation completed 
+            // sucessfully (no exception)
+            base.SetAsCompleted(null, completedSynchronously);
+        }
+
+        new public TResult EndInvoke()
+        {
+            base.EndInvoke(); // Wait until operation has completed 
+            return m_result;  // Return the result (if above didn't throw)
+        }
+    }
+}
Index: Enyim.Caching/Threading/AsyncResultNoResult.cs
===================================================================
--- Enyim.Caching/Threading/AsyncResultNoResult.cs	(revision 0)
+++ Enyim.Caching/Threading/AsyncResultNoResult.cs	(revision 0)
@@ -0,0 +1,123 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+
+namespace Enyim.Caching.Threading
+{
+    internal class AsyncResultNoResult : IAsyncResult
+    {
+        // Fields set at construction which never change while 
+        // operation is pending
+        private readonly AsyncCallback m_AsyncCallback;
+        private readonly Object m_AsyncState;
+
+        // Fields set at construction which do change after 
+        // operation completes
+        private const Int32 c_StatePending = 0;
+        private const Int32 c_StateCompletedSynchronously = 1;
+        private const Int32 c_StateCompletedAsynchronously = 2;
+        private Int32 m_CompletedState = c_StatePending;
+
+        // Field that may or may not get set depending on usage
+        private ManualResetEvent m_AsyncWaitHandle;
+
+        // Fields set when operation completes
+        private Exception m_exception;
+
+        public AsyncResultNoResult(AsyncCallback asyncCallback, Object state)
+        {
+            m_AsyncCallback = asyncCallback;
+            m_AsyncState = state;
+        }
+
+        public void SetAsCompleted(
+           Exception exception, Boolean completedSynchronously)
+        {
+            // Passing null for exception means no error occurred. 
+            // This is the common case
+            m_exception = exception;
+
+            // The m_CompletedState field MUST be set prior calling the callback
+            Int32 prevState = Interlocked.Exchange(ref m_CompletedState,
+               completedSynchronously ? c_StateCompletedSynchronously :
+               c_StateCompletedAsynchronously);
+            if (prevState != c_StatePending)
+                throw new InvalidOperationException(
+                    "You can set a result only once");
+
+            // If the event exists, set it
+            if (m_AsyncWaitHandle != null) m_AsyncWaitHandle.Set();
+
+            // If a callback method was set, call it
+            if (m_AsyncCallback != null) m_AsyncCallback(this);
+        }
+
+        public void EndInvoke()
+        {
+            // This method assumes that only 1 thread calls EndInvoke 
+            // for this object
+            if (!IsCompleted)
+            {
+                // If the operation isn't done, wait for it
+                AsyncWaitHandle.WaitOne();
+                AsyncWaitHandle.Close();
+                m_AsyncWaitHandle = null;  // Allow early GC
+            }
+
+            // Operation is done: if an exception occured, throw it
+            if (m_exception != null) throw m_exception;
+        }
+
+        #region Implementation of IAsyncResult
+        public Object AsyncState { get { return m_AsyncState; } }
+
+        public Boolean CompletedSynchronously
+        {
+            get
+            {
+                return Thread.VolatileRead(ref m_CompletedState) ==
+                    c_StateCompletedSynchronously;
+            }
+        }
+
+        public WaitHandle AsyncWaitHandle
+        {
+            get
+            {
+                if (m_AsyncWaitHandle == null)
+                {
+                    Boolean done = IsCompleted;
+                    ManualResetEvent mre = new ManualResetEvent(done);
+                    if (Interlocked.CompareExchange(ref m_AsyncWaitHandle,
+                       mre, null) != null)
+                    {
+                        // Another thread created this object's event; dispose 
+                        // the event we just created
+                        mre.Close();
+                    }
+                    else
+                    {
+                        if (!done && IsCompleted)
+                        {
+                            // If the operation wasn't done when we created 
+                            // the event but now it is done, set the event
+                            m_AsyncWaitHandle.Set();
+                        }
+                    }
+                }
+                return m_AsyncWaitHandle;
+            }
+        }
+
+        public Boolean IsCompleted
+        {
+            get
+            {
+                return Thread.VolatileRead(ref m_CompletedState) !=
+                    c_StatePending;
+            }
+        }
+        #endregion
+    }
+}