在F#中,我可以使用F#异步目录访问者C#
// Synchronous version
let rec folderCollectorSync path =
try
let dirs = Directory.GetDirectories path
for z in dirs do folderCollectorSync z
with
| ex ->()
// Asynchronous version that uses synchronous when 'nesting <= 0'
let rec folderCollector path nesting =
async { if nesting <= 0 then return folderCollectorSync path
else
try
let dirs = Directory.GetDirectories path
do! [for z in dirs -> folderCollector z (nesting - 1) ]
|> Async.Parallel |> Async.Ignore
with ex ->() }
folderCollector @"C:\" 5 |> Async.RunSynchronously
旅行目录异步的第5级。
我试着重做上面的代码(当然,没有使用Async.Parallel
)。
它看起来是这样的:
static void TravelSync(string path, CountdownEvent cd)
{
var dirs = Directory.GetDirectories(path);
var cdown = new CountdownEvent(dirs.Length);
foreach (var d in dirs)
TravelSync(d, cdown);
cdown.Wait();
cd.Signal();
}
static void Travel(string path, int nesting, CountdownEvent cd)
{
if (!Directories.Contains(path))
{
if (nesting <= 0)
{
TravelSync(path, cd);
}
else
{
Messages.Add(path);
Directories.Add(path);
var dirs = Directory.GetDirectories(path);
var cdown = new CountdownEvent(dirs.Length);
foreach (var d in dirs)
ThreadPool.QueueUserWorkItem(o => Travel(d, nesting - 1, cdown));
cdown.Wait();
cd.Signal();
}
}
}
通过难怪C#版本是缓慢的地狱,并且还只是停止后已经爬5个目录。
所以我的问题是:F#如何跟踪异步操作?我的C#版本很差,并且有很多性能问题。
我知道我只是可以在我的C#项目中使用F#代码,但由于这只是练习,我更感兴趣的是如何在C#中完成它。
要创建工作项进入线程池的第5级 - 这就是(根据您的目录设置)远得多,因为所有的开销。您可以尝试C#(CTP)中较新的等待支持或减少嵌套。 – Carsten
@CarstenKönig,是吗?那么F#版本,它工作正常?我的问题是F#知道所有的异步操作何时完成,然后解除主线程的阻塞。 – ebb