所以我想确保我的应用程序的UI线程上没有发生所有数据库/网络操作。为此,我通常使用BeginInvoke函数进行调用,然后使用Invoke进行实际更新。我不确定我是否正在做正确的事情与应该做的事情相比。任何人都可以提供以下代码的评论:
private void folderTree_NodeExpandedChanged(object sender, RadTreeViewEventArgs e)
{
if (e.Node.Tag != null)
{
var path = (string) e.Node.Tag;
if (!string.IsNullOrEmpty(path))
{
if (Directory.Exists(path))
{
folderTree.BeginUpdate();
BeginInvoke(
new Action(() => GetDirectories(path, e.Node)));
folderTree.EndUpdate();
}
}
}
}
private void GetDirectories(string path, RadTreeNode parent)
{
var dirs = (new DirectoryInfo(path)).GetDirectories();
Array.ForEach(dirs, d => Invoke(new Action(
() => AddNode(d.Name, d.FullName, parent))));
}
答案 0 :(得分:3)
在控件/表单上,BeginInvoke
通过消息泵将工作推送到UI线程(该特权产生的开销很小)。所以你已经从UI线程转到了UI线程......我怀疑你想在这里某处BackgroundWorker
/ ThreadPool
或类似的东西......(也许ThreadPool
最简单从目前的位置)。
也;您可能不希望同步进行更新工作,并且您不希望线程之间进行大量切换;我将整个阵列传递(或中等大小的块);不是个人记录。
答案 1 :(得分:0)
据我所知,以下电话:
BeginInvoke(new Action(() => GetDirectories(path, e.Node)));
......与这一点差别不大:
GetDirectories(path, e.Node);
它只在调用周围增加了一两层,但是没有异步;这一切都发生在同一个线程上。您需要包含一些机制来将工作推送到另一个线程(BackgroundWorker
控件,使用ThreadPool
或类似的东西)
答案 2 :(得分:0)
您可能会找到BackgroundWorker类,这是一个更简单的选项。
答案 3 :(得分:0)
我会这样做。虽然没有试过这个代码,但它应该可以工作。
public class ParameterInfo
{
string _path;
RadTreeNode _parent;
}
if (!ThreadPool.QueueUserWorkItem(new WaitCallback(GetDirectories),
new ParameterInfo
{
_path = path,
_parent = e.Node
}))
{
//should log, if a thread has not been created
}
private void GetDirectories(ParameterInfo param)
{
var dirs = (new DirectoryInfo(param._path)).GetDirectories();
Array.ForEach(dirs, d => BeginInvoke( new Action(
() => AddNode(d.Name, d.FullName, param._parent) )
));
}