diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index b9e26573518a14de30f4e0c97eaf157a34b9b157..acec68f39321a80941e1705e42b6aaec3b2fede3 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -42,6 +42,7 @@
 #include "llagentlanguage.h"
 #include "llagentui.h"
 #include "llagentwearables.h"
+#include "lldirpicker.h"
 #include "llfloaterimcontainer.h"
 #include "llimprocessing.h"
 #include "llwindow.h"
@@ -1985,6 +1986,7 @@ bool LLAppViewer::cleanup()
 	mAppCoreHttp.cleanup();
 
 	SUBSYSTEM_CLEANUP(LLFilePickerThread);
+	SUBSYSTEM_CLEANUP(LLDirPickerThread);
 
 	//MUST happen AFTER SUBSYSTEM_CLEANUP(LLCurl)
 	delete sTextureCache;
@@ -2155,6 +2157,7 @@ bool LLAppViewer::initThreads()
 	gMeshRepo.init();
 
 	LLFilePickerThread::initClass();
+	LLDirPickerThread::initClass();
 
 	// *FIX: no error handling here!
 	return true;
@@ -4589,7 +4592,7 @@ void LLAppViewer::idle()
 	LLSmoothInterpolation::updateInterpolants();
 	LLMortician::updateClass();
 	LLFilePickerThread::clearDead();  //calls LLFilePickerThread::notify()
-
+	LLDirPickerThread::clearDead();
 	F32 dt_raw = idle_timer.getElapsedTimeAndResetF32();
 
 	// Cap out-of-control frame times
diff --git a/indra/newview/lldirpicker.cpp b/indra/newview/lldirpicker.cpp
index 5c4f0f4d5dbb460c580bc3c45947482421b03ad4..768b1c20219beacbdfc4e829c949cdc160c3d87f 100644
--- a/indra/newview/lldirpicker.cpp
+++ b/indra/newview/lldirpicker.cpp
@@ -77,6 +77,14 @@ LLDirPicker::LLDirPicker() :
 	mFileName(NULL),
 	mLocked(false)
 {
+	bi.hwndOwner = NULL;
+	bi.pidlRoot = NULL;
+	bi.pszDisplayName = NULL;
+	bi.lpszTitle = NULL;
+	bi.ulFlags = BIF_USENEWUI;
+	bi.lpfn = NULL;
+	bi.lParam = NULL;
+	bi.iImage = 0;
 }
 
 LLDirPicker::~LLDirPicker()
@@ -84,7 +92,7 @@ LLDirPicker::~LLDirPicker()
 	// nothing
 }
 
-BOOL LLDirPicker::getDir(std::string* filename)
+BOOL LLDirPicker::getDir(std::string filename, bool blocking)
 {
 	if( mLocked )
 	{
@@ -99,39 +107,39 @@ BOOL LLDirPicker::getDir(std::string* filename)
 
 	BOOL success = FALSE;
 
-	// Modal, so pause agent
-	send_agent_pause();
-
-   BROWSEINFO bi;
-   memset(&bi, 0, sizeof(bi));
-
-   bi.ulFlags   = BIF_USENEWUI;
-   bi.hwndOwner = (HWND)gViewerWindow->getPlatformWindow();
-   bi.lpszTitle = NULL;
-
-   ::OleInitialize(NULL);
+	
+	if (blocking)
+	{
+		// Modal, so pause agent
+		send_agent_pause();
+	}
 
-   LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi);
+	bi.hwndOwner = (HWND)gViewerWindow->getPlatformWindow();
 
-   if(pIDL != NULL)
-   {
-      WCHAR buffer[_MAX_PATH] = {'\0'};
+	::OleInitialize(NULL);
+	LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi);
 
-      if(::SHGetPathFromIDList(pIDL, buffer) != 0)
-      {
-		  	// Set the string value.
+	if(pIDL != NULL)
+	{
+		WCHAR buffer[_MAX_PATH] = {'\0'};
 
-   			mDir = utf16str_to_utf8str(llutf16string(buffer));
-	         success = TRUE;
-      }
+		if(::SHGetPathFromIDList(pIDL, buffer) != 0)
+		{
+			// Set the string value.
 
-      // free the item id list
-      CoTaskMemFree(pIDL);
-   }
+			mDir = utf16str_to_utf8str(llutf16string(buffer));
+			success = TRUE;
+		}
+		// free the item id list
+		CoTaskMemFree(pIDL);
+	}
 
-   ::OleUninitialize();
+	::OleUninitialize();
 
-	send_agent_resume();
+	if (blocking)
+	{
+		send_agent_resume();
+	}
 
 	// Account for the fact that the app has been stalled.
 	LLFrameTimer::updateFrameTime();
@@ -267,3 +275,94 @@ std::string LLDirPicker::getDirName()
 }
 
 #endif
+
+
+LLMutex* LLDirPickerThread::sMutex = NULL;
+std::queue<LLDirPickerThread*> LLDirPickerThread::sDeadQ;
+
+void LLDirPickerThread::getFile()
+{
+#if LL_WINDOWS
+	start();
+#else
+	run();
+#endif
+}
+
+//virtual 
+void LLDirPickerThread::run()
+{
+#if LL_WINDOWS
+	bool blocking = false;
+#else
+	bool blocking = true; // modal
+#endif
+
+	LLDirPicker picker;
+
+	if (picker.getDir(mProposedName, blocking))
+	{
+		mResponses.push_back(picker.getDirName());
+	}	
+
+	{
+		LLMutexLock lock(sMutex);
+		sDeadQ.push(this);
+	}
+
+}
+
+//static
+void LLDirPickerThread::initClass()
+{
+	sMutex = new LLMutex(NULL);
+}
+
+//static
+void LLDirPickerThread::cleanupClass()
+{
+	clearDead();
+
+	delete sMutex;
+	sMutex = NULL;
+}
+
+//static
+void LLDirPickerThread::clearDead()
+{
+	if (!sDeadQ.empty())
+	{
+		LLMutexLock lock(sMutex);
+		while (!sDeadQ.empty())
+		{
+			LLDirPickerThread* thread = sDeadQ.front();
+			thread->notify(thread->mResponses);
+			delete thread;
+			sDeadQ.pop();
+		}
+	}
+}
+
+LLDirPickerThread::LLDirPickerThread(const dir_picked_signal_t::slot_type& cb, const std::string &proposed_name)
+	: LLThread("dir picker"),
+	mFilePickedSignal(NULL)
+{
+	mFilePickedSignal = new dir_picked_signal_t();
+	mFilePickedSignal->connect(cb);
+}
+
+LLDirPickerThread::~LLDirPickerThread()
+{
+	delete mFilePickedSignal;
+}
+
+void LLDirPickerThread::notify(const std::vector<std::string>& filenames)
+{
+	if (!filenames.empty())
+	{
+		if (mFilePickedSignal)
+		{
+			(*mFilePickedSignal)(filenames, mProposedName);
+		}
+	}
+}
diff --git a/indra/newview/lldirpicker.h b/indra/newview/lldirpicker.h
index 8656b23afd670314542ddf58eb85d20955cdfc54..c1087c70acf727ff4b15461592f0e2f51634521b 100644
--- a/indra/newview/lldirpicker.h
+++ b/indra/newview/lldirpicker.h
@@ -33,6 +33,13 @@
 
 #include "stdtypes.h"
 
+#include "llthread.h"
+#include <queue>
+
+#if LL_WINDOWS
+#include <shlobj.h>
+#endif
+
 #if LL_DARWIN
 
 // AssertMacros.h does bad things.
@@ -53,7 +60,7 @@ class LLDirPicker
 	// calling this before main() is undefined
 	static LLDirPicker& instance( void ) { return sInstance; }
 
-	BOOL getDir(std::string* filename);
+	BOOL getDir(std::string filename, bool blocking = true);
 	std::string getDirName();
 
 	// clear any lists of buffers or whatever, and make sure the dir
@@ -76,11 +83,15 @@ class LLDirPicker
 	LLFilePicker *mFilePicker;
 #endif
 
+
 	std::string* mFileName;
 	std::string  mDir;
 	bool mLocked;
 
 	static LLDirPicker sInstance;
+#if LL_WINDOWS
+	BROWSEINFO bi;
+#endif
 	
 public:
 	// don't call these directly please.
@@ -88,4 +99,33 @@ class LLDirPicker
 	~LLDirPicker();
 };
 
+class LLDirPickerThread : public LLThread
+{
+public:
+
+	static std::queue<LLDirPickerThread*> sDeadQ;
+	static LLMutex* sMutex;
+
+	static void initClass();
+	static void cleanupClass();
+	static void clearDead();
+
+	std::vector<std::string> mResponses;
+	std::string mProposedName;
+
+	typedef boost::signals2::signal<void(const std::vector<std::string>& filenames, std::string proposed_name)> dir_picked_signal_t;
+
+	LLDirPickerThread(const dir_picked_signal_t::slot_type& cb, const std::string &proposed_name);
+	~LLDirPickerThread();
+
+	void getFile();
+
+	virtual void run();
+
+	virtual void notify(const std::vector<std::string>& filenames);
+
+private:
+	dir_picked_signal_t*		mFilePickedSignal;
+};
+
 #endif
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 9d723bdd9de16ead341a7d253bf27a24eb67371b..4ce35643b13ba9136740a7b5842ba232f0c283e4 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -1096,16 +1096,15 @@ void LLFloaterPreference::onClickSetCache()
 	
 	std::string proposed_name(cur_name);
 
-	LLDirPicker& picker = LLDirPicker::instance();
-	if (! picker.getDir(&proposed_name ) )
-	{
-		return; //Canceled!
-	}
+	(new LLDirPickerThread(boost::bind(&LLFloaterPreference::changeCachePath, this, _1, _2), proposed_name))->getFile();
+}
 
-	std::string dir_name = picker.getDirName();
-	if (!dir_name.empty() && dir_name != cur_name)
+void LLFloaterPreference::changeCachePath(const std::vector<std::string>& filenames, std::string proposed_name)
+{
+	std::string dir_name = filenames[0];
+	if (!dir_name.empty() && dir_name != proposed_name)
 	{
-		std::string new_top_folder(gDirUtilp->getBaseFileName(dir_name));	
+		std::string new_top_folder(gDirUtilp->getBaseFileName(dir_name));
 		LLNotificationsUtil::add("CacheWillBeMoved");
 		gSavedSettings.setString("NewCacheLocation", dir_name);
 		gSavedSettings.setString("NewCacheLocationTopFolder", new_top_folder);
@@ -1744,25 +1743,21 @@ void LLFloaterPreference::onClickLogPath()
 	std::string proposed_name(gSavedPerAccountSettings.getString("InstantMessageLogPath"));	 
 	mPriorInstantMessageLogPath.clear();
 	
-	LLDirPicker& picker = LLDirPicker::instance();
-	//Launches a directory picker and waits for feedback
-	if (!picker.getDir(&proposed_name ) )
-	{
-		return; //Canceled!
-	}
 
-	//Gets the path from the directory picker
-	std::string dir_name = picker.getDirName();
+	(new LLDirPickerThread(boost::bind(&LLFloaterPreference::changeLogPath, this, _1, _2), proposed_name))->getFile();
+}
 
+void LLFloaterPreference::changeLogPath(const std::vector<std::string>& filenames, std::string proposed_name)
+{
 	//Path changed
-	if(proposed_name != dir_name)
+	if (proposed_name != filenames[0])
 	{
-	gSavedPerAccountSettings.setString("InstantMessageLogPath", dir_name);
+		gSavedPerAccountSettings.setString("InstantMessageLogPath", filenames[0]);
 		mPriorInstantMessageLogPath = proposed_name;
-	
-	// enable/disable 'Delete transcripts button
-	updateDeleteTranscriptsButton();
-}
+
+		// enable/disable 'Delete transcripts button
+		updateDeleteTranscriptsButton();
+	}
 }
 
 bool LLFloaterPreference::moveTranscriptsAndLog()
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index 0cd7bac20fc3f22047c8089ab98a3c4e46351538..8339a182965cc0e810520851f9b189af8255ee7d 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -133,6 +133,7 @@ class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver,
 	void setCacheLocation(const LLStringExplicit& location);
 
 	void onClickSetCache();
+	void changeCachePath(const std::vector<std::string>& filenames, std::string proposed_name);
 	void onClickResetCache();
 	void onClickSkin(LLUICtrl* ctrl,const LLSD& userdata);
 	void onSelectSkin();
@@ -145,6 +146,7 @@ class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver,
 	void resetAllIgnored();
 	void setAllIgnored();
 	void onClickLogPath();
+	void changeLogPath(const std::vector<std::string>& filenames, std::string proposed_name);
 	bool moveTranscriptsAndLog();
 	void enableHistory();
 	void setPersonalInfo(const std::string& visibility, bool im_via_email, bool is_verified_email);