- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在测试 WPF 项目中,我尝试使用 TPL 数据流来枚举给定父目录的所有子目录,并创建具有特定文件扩展名的文件列表,例如“.xlsx”。我使用 2 个 block ,第一个 dirToFilesBlock,最后一个 fileActionBlock。
为了创建遍历所有子目录的递归效果,第一个 block 有一个返回自身的链接,链接谓词测试以查看输出项是否为目录。这是我在一本关于异步编程的书中找到的方法。第二个链接指向 fileActionBlock,然后根据链接谓词测试将文件添加到列表,以查看文件是否具有正确的扩展名。
我遇到的问题是在使用 btnStart_Click 启动之后,它永远不会完成。也就是说,我们永远不会到达事件处理程序中的等待下方以显示“已完成”消息。我知道我可能需要调用 dirToFilesBlock.Complete(),但我不知道它应该在代码中的什么位置以及在什么条件下调用?我不能在最初的帖子之后调用它,因为它会停止返回子目录的链接。我试过使用 InputCount 和 OutputCount 属性做一些事情,但没有取得太大进展。如果可能的话,我希望保持数据流的结构不变,因为这意味着我还可以使用每个新目录更新 UI,通过返回链接向用户提供一些进度反馈。
我是 TPL 数据流的新手,非常感谢收到任何帮助。
这是代码隐藏文件中的代码:
public partial class MainWindow : Window
{
TransformManyBlock<string, string> dirToFilesBlock;
ActionBlock<string> fileActionBlock;
ObservableCollection<string> files;
CancellationTokenSource cts;
CancellationToken ct;
public MainWindow()
{
InitializeComponent();
files = new ObservableCollection<string>();
lst.DataContext = files;
cts = new CancellationTokenSource();
ct = cts.Token;
}
private Task Start(string path)
{
var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
dirToFilesBlock = new TransformManyBlock<string, string>((Func<string, IEnumerable<string>>)(GetFileSystemItems), new ExecutionDataflowBlockOptions() { CancellationToken = ct });
fileActionBlock = new ActionBlock<string>((Action<string>)ProcessFile, new ExecutionDataflowBlockOptions() {CancellationToken = ct, TaskScheduler = uiScheduler});
// Order of LinkTo's important here!
dirToFilesBlock.LinkTo(dirToFilesBlock, new DataflowLinkOptions() { PropagateCompletion = true }, IsDirectory);
dirToFilesBlock.LinkTo(fileActionBlock, new DataflowLinkOptions() { PropagateCompletion = true }, IsRequiredDocType);
// Kick off the recursion.
dirToFilesBlock.Post(path);
return Task.WhenAll(dirToFilesBlock.Completion, fileActionBlock.Completion);
}
private bool IsDirectory(string path)
{
return Directory.Exists(path);
}
private bool IsRequiredDocType(string fileName)
{
return System.IO.Path.GetExtension(fileName) == ".xlsx";
}
private IEnumerable<string> GetFilesInDirectory(string path)
{
// Check for cancellation with each new dir.
ct.ThrowIfCancellationRequested();
// Check in case of Dir access problems
try
{
return Directory.EnumerateFileSystemEntries(path);
}
catch (Exception)
{
return Enumerable.Empty<string>();
}
}
private IEnumerable<string> GetFileSystemItems(string dir)
{
return GetFilesInDirectory(dir);
}
private void ProcessFile(string fileName)
{
ct.ThrowIfCancellationRequested();
files.Add(fileName);
}
private async void btnStart_Click(object sender, RoutedEventArgs e)
{
try
{
await Start(@"C:\");
// Never gets here!!!
MessageBox.Show("Completed");
}
catch (OperationCanceledException)
{
MessageBox.Show("Cancelled");
}
catch (Exception)
{
MessageBox.Show("Unknown err");
}
finally
{
}
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
cts.Cancel();
}
}
最佳答案
即使这是一个老问题,在数据流循环中处理完成仍然是一个问题。
在您的情况下,您可以让 TransfomBlock
对仍在飞行中的项目进行计数。这表明该 block 正忙于处理任意数量的项目。然后,您只会在 block 不忙且两个缓冲区都为空时才调用 Complete()
。您可以在我写的帖子中找到有关处理完成的更多信息 Finding Completion in a Complex Flow: Feedback Loops
public partial class MainWindow : Window {
TransformManyBlock<string, string> dirToFilesBlock;
ActionBlock<string> fileActionBlock;
ObservableCollection<string> files;
CancellationTokenSource cts;
CancellationToken ct;
public MainWindow() {
InitializeComponent();
files = new ObservableCollection<string>();
lst.DataContext = files;
cts = new CancellationTokenSource();
ct = cts.Token;
}
private async Task Start(string path) {
var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
dirToFilesBlock = new TransformManyBlock<string, string>((Func<string, IEnumerable<string>>)(GetFileSystemItems), new ExecutionDataflowBlockOptions() { CancellationToken = ct });
fileActionBlock = new ActionBlock<string>((Action<string>)ProcessFile, new ExecutionDataflowBlockOptions() { CancellationToken = ct, TaskScheduler = uiScheduler });
// Order of LinkTo's important here!
dirToFilesBlock.LinkTo(dirToFilesBlock, new DataflowLinkOptions() { PropagateCompletion = true }, IsDirectory);
dirToFilesBlock.LinkTo(fileActionBlock, new DataflowLinkOptions() { PropagateCompletion = true }, IsRequiredDocType);
// Kick off the recursion.
dirToFilesBlock.Post(path);
await ProcessingIsComplete();
dirToFilesBlock.Complete();
await Task.WhenAll(dirToFilesBlock.Completion, fileActionBlock.Completion);
}
private async Task ProcessingIsComplete() {
while (!ct.IsCancellationRequested && DirectoryToFilesBlockIsIdle()) {
await Task.Delay(500);
}
}
private bool DirectoryToFilesBlockIsIdle() {
return dirToFilesBlock.InputCount == 0 &&
dirToFilesBlock.OutputCount == 0 &&
directoriesBeingProcessed <= 0;
}
private bool IsDirectory(string path) {
return Directory.Exists(path);
}
private bool IsRequiredDocType(string fileName) {
return System.IO.Path.GetExtension(fileName) == ".xlsx";
}
private int directoriesBeingProcessed = 0;
private IEnumerable<string> GetFilesInDirectory(string path) {
Interlocked.Increment(ref directoriesBeingProcessed)
// Check for cancellation with each new dir.
ct.ThrowIfCancellationRequested();
// Check in case of Dir access problems
try {
return Directory.EnumerateFileSystemEntries(path);
} catch (Exception) {
return Enumerable.Empty<string>();
} finally {
Interlocked.Decrement(ref directoriesBeingProcessed);
}
}
private IEnumerable<string> GetFileSystemItems(string dir) {
return GetFilesInDirectory(dir);
}
private void ProcessFile(string fileName) {
ct.ThrowIfCancellationRequested();
files.Add(fileName);
}
private async void btnStart_Click(object sender, RoutedEventArgs e) {
try {
await Start(@"C:\");
// Never gets here!!!
MessageBox.Show("Completed");
} catch (OperationCanceledException) {
MessageBox.Show("Cancelled");
} catch (Exception) {
MessageBox.Show("Unknown err");
} finally {
}
}
private void btnCancel_Click(object sender, RoutedEventArgs e) {
cts.Cancel();
}
}
关于c# - 涉及递归未完成的 TPL 数据流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37054930/
下面的代码已经工作了一段时间,但突然停止返回: await availableChangedPublishEndpoint .Publish( AvailableStockCou
我正在尝试使用 NSMetaDataQuery 在 iCloud 中探索我的应用可用的文件。我能够开始查询,但它永远不会结束。这是我的代码。 func report1() { let file
这是我的 Gulp 任务: //Image Optimization gulp.task( 'imagemin', function () { return gulp.src( imageDi
此代码片段已编译: 让测试= 让 x = 1 printfn "%A"x 如果最后一行被删除,则会出现以下编译错误: 错误 FS0588:此“让”之后的 block 未完成。期待一个表情。 这条消息是
很抱歉一直询问有关 Powershell 的问题,我的 script-foo 不是它需要的。 我正在编写一个 BitsTransfer .PS1 来自动每周下载一个 ASCII 文件。 它似乎永远不会
我最近使用了相当多的 SwingWorkers,并且遇到了一些问题,因此我尝试创建一个 SCSSE,但这显然不起作用 static SwingWorker worker; public static
我有一个包含 DatePickerDialog 的 DialogFragment。每当我设置日期时,一项新 Activity 就会开始。当我按回去时,它会返回到相同的 Activity 。为什么 Ac
我实现了一个 PhoneStateListener 如何在您被调用时停止音频并在您完成后再次启动它。当我通过 finish() 退出我的应用程序时,PhoneStateListener 似乎仍然处于
这是建立在另一个问题上, Left join and only last row from right 我尝试使用相同的策略编写第二个连接。我在我的 dev macbook pro 上运行 postg
我正在使用 XMLHttpRequest 调用 PHP 文件,但现在调用未完成,我不知道为什么。 req.readyState 不是 4,我不知道为什么,因为 PHP 文件没问题,并且完全执行了预期的
我需要为一系列图像制作动画。 // Animate Circle let duration = 1.0 circleGroup.setBackgroundImageNamed("arc") circl
此方法永远不会通过 foreach 循环。无论我在它后面放什么,它都不会运行。即使 book 对象中没有联系人对象,它也不应该跳过其余代码。这被用于我正在开发的应用程序中的联系人选择器,关于这里发生的
我刚刚开始学习 python,我想看看是否可以制作 monty Hall 问题的 python 版本。当我使用 1 或 2 次迭代时,一切似乎都在小范围内工作,但超过此后,一切都不起作用了。 for
是否有任何原因导致 Activity 可能未完成(即调用其 finalize())并因此被垃圾收集,即使它的 onDestroy() 已被调用?这只是您每天的平均内存泄漏吗? 最佳答案 onDestr
我正在尝试访问 Twitter 帐户,但此代码在 accountTypeWithAccountTypeIdentifier 行停止。 我的代码看起来像这样,我运行的是 iOS 6: #import
这个问题在这里已经有了答案: An async/await example that causes a deadlock (5 个回答) 4年前关闭。 我是 C# 任务的新手,遇到了一个我不理解的问题
我正在尝试在 linux 服务器上以非 GUI 模式运行 JMX 文件。使用 SFTP 协议(protocol)尝试将文件上传到对象存储。下面是脚本和用于运行脚本的配置。 测试.jmx import
我正在尝试等待 getJson 调用并处理返回的数据。我看过很多答案,并尝试使用 $.ajax 的 async: false(不起作用,因为查询是跨域的)、回调和.done 基本 $.ajax 调用的
我有一个带有 echo 的 php 代码来检查它停止的位置(它不会崩溃,但会停止发送 echo 并且不能按预期工作) $stmt=$conexion->prepare("SELECT Email, M
我是 Scala 的新手,我想知道是否有一些方法可以创建一个虚拟的 Future 对象来模拟 isCompleted 到 false。我需要这个用于测试目的。 目前我用来制作虚拟Future[Int]
我是一名优秀的程序员,十分优秀!