I've made an asynchronous loading system similiar to what you want.
I use a task system, that keeps some threads (you can control how many you want) in a pool, waiting for tasks, and executes them in the background. I always use thread-safe message queues to communicate between the threads and the queue blocks when it doesn't have anything, so the threads only wake up when there's anything to do.
I also have a ResourceManager class, that the rest of the engine uses to request resources. If they are not already cached, then I create a new task which I submit to the task system. When the background thread completes the loading, it queues a message in the ResourceManager saying the loading finished, and once that happens the Resource itself is changed to the Loaded state, and I notify whoever subscribed to the onResourceLoaded event.
It currently returns reference counting pointers. These are safe for multithreaded use by using atomic operations, the InterlockedExchange functions that were talked about earlier. I'm currently thinking of switching to a handle-based system, as pointers makes it harder to support resource reloading at runtime. Currently I need to notify everything that there the pointer of a resource changed.
Here is the code where the magic happens, hope it helps.