Одним из самых простых способов запуска асинхронного процесса является использование анонимного делегата с BeginInvoke.Например, вы можете переместить ваш код в конструкторе в отдельный метод (скажем, RenderTreeView), а затем вызвать его асинхронно, чтобы начать новый поток следующим образом:
Action action = RenderTreeView;
action.BeginInvoke(null, null);
Фокус в том, что в любое время вывзаимодействовать с любыми элементами пользовательского интерфейса из асинхронного процесса, необходимого для повторного присоединения к основному потоку пользовательского интерфейса, в противном случае вы получите исключение о доступе между потоками.Это относительно просто.
В Windows Forms это:
if (InvokeRequired)
Invoke(new MethodInvoker({item.Items.Add(subitem)}));
else
item.Items.Add(subitem);
В WPF это:
if (!Dispatcher.CheckAccess())
Dispatcher.Invoke(new Action(() => item.Items.Add(subitem)));
else
item.Items.Add(subitem);
Вам действительно нужно разбить код насделать его более гибким с точки зрения методов.На данный момент все объединено в один метод, который затрудняет работу и повторный фактор для асинхронных процессов.
Обновление Вот и все :)
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;
}
}