One of the easiest ways to start an asynchronous process is to use an anonymous delegate with BeginInvoke. As an example, you can move your code in the constructor into a separate method (say, RenderTreeView), and then call it asynchronously to start a new thread as follows:
Action action = RenderTreeView; action.BeginInvoke(null, null);
The trick is that at any time when you interact with any user interface elements from the asynchronization process, you need to connect to the main user interface thread, otherwise you will get an exception from access to cross-threads. It is also relatively straightforward.
On Windows Forms, this is:
if (InvokeRequired) Invoke(new MethodInvoker({item.Items.Add(subitem)})); else item.Items.Add(subitem);
In WPF, this is:
if (!Dispatcher.CheckAccess()) Dispatcher.Invoke(new Action(() => item.Items.Add(subitem))); else item.Items.Add(subitem);
You really need to break the code to make it more flexible in terms of methods. At the moment, everything is connected in one method, because of which it is difficult to work and refactor for asynchronous processes.
Update Here you go :)
public partial class MainWindow : Window { private readonly object dummyNode = null; public MainWindow() { InitializeComponent(); Action<ItemCollection> action = RenderTreeView; action.BeginInvoke(treeView1.Items, null, null); } private void RenderTreeView(ItemCollection root) { foreach (string drive in Directory.GetLogicalDrives()) { var driveInfo = new DriveInfo(drive); if (driveInfo.IsReady) { CreateAndAppendTreeViewItem(root, drive, drive, drive); } } } private void FolderExpanded(object sender, RoutedEventArgs e) { var item = (TreeViewItem) sender; if (item.Items.Count == 1 && item.Items[0] == dummyNode) { item.Items.Clear(); var directory = item.Tag as string; if (string.IsNullOrEmpty(directory)) { return; } Action<TreeViewItem, string> action = ExpandTreeViewNode; action.BeginInvoke(item, directory, null, null); } } private void ExpandTreeViewNode(TreeViewItem item, string directory) { foreach (string dir in Directory.GetDirectories(directory)) { var tempDirInfo = new DirectoryInfo(dir); bool isSystem = ((tempDirInfo.Attributes & FileAttributes.System) == FileAttributes.System); if (!isSystem) { CreateAndAppendTreeViewItem(item.Items, tempDirInfo.Name, dir, dir); } } } private void AddChildNodeItem(ItemCollection collection, TreeViewItem subItem) { if (Dispatcher.CheckAccess()) { collection.Add(subItem); } else { Dispatcher.Invoke(new Action(() => AddChildNodeItem(collection, subItem))); } } private void CreateAndAppendTreeViewItem(ItemCollection items, string header, string tag, string toolTip) { if (Dispatcher.CheckAccess()) { var subitem = CreateTreeViewItem(header, tag, toolTip); AddChildNodeItem(items, subitem); } else { Dispatcher.Invoke(new Action(() => CreateAndAppendTreeViewItem(items, header, tag, toolTip))); } } private TreeViewItem CreateTreeViewItem(string header, string tag, string toolTip) { var treeViewItem = new TreeViewItem {Header = header, Tag = tag, ToolTip = toolTip}; treeViewItem.Items.Add(dummyNode); treeViewItem.Expanded += FolderExpanded; return treeViewItem; } }