我有一个Regex
,在处理某些文件时可能会导致死循环。虽然我迟早会解决这个问题,但为了安全起见,我想在可取消的任务中运行它。
我在这里读到了一些答案,但以下解决方案都不起作用。有什么帮助吗?
public static Task<CodeFile> CreateCodeFile(string fileName)
{
var fileInfo = new FileInfo(fileName);
foreach (var codeFileFactory in CodeFileFactories)
{
var cancellationTokenSource = new CancellationTokenSource();
cancellationTokenSource.CancelAfter(1000);
var task = new Task<CodeFile>(() => TryToCreateCodeFile(codeFileFactory, fileInfo),
cancellationTokenSource.Token);
task.RunSynchronously(); //Get lost here.
if (!task.Wait(1000))
cancellationTokenSource.Cancel();
File.WriteAllTextAsync("FailedLog.txt",
File.ReadAllTextAsync("FailedLog.txt") + "rn" + fileName);
cancellationTokenSource.Dispose();
return task;
}
return null;
}
或:
public static async Task<CodeFile> CreateCodeFile(string fileName)
{
var fileInfo = new FileInfo(fileName);
foreach (var codeFileFactory in CodeFileFactories)
{
var cancellationTokenSource = new CancellationTokenSource();
try
{
cancellationTokenSource.CancelAfter(1000);
var codeFile = await Task.Run(() => TryToCreateCodeFile(codeFileFactory, fileInfo),
cancellationTokenSource.Token); //Get lost here.
if (codeFile != null)
return codeFile;
}
catch (TaskCanceledException)
{
File.WriteAllTextAsync("FailedLog.txt",
File.ReadAllTextAsync("FailedLog.txt") + "rn" + fileName);
}
finally
{
cancellationTokenSource.Dispose();
}
}
return null;
}
这里是要调用的函数:
private static CodeFile TryToCreateCodeFile(ICodeFileFactory codeFileFactory, FileInfo fileInfo)
{
var codeFile = codeFileFactory.CreateByName(fileInfo);
return codeFile;
//Somewhere deeper, .net Regex.Matches() caused the dead loop which I cannot control.
}
在这个主题CancellationTokenSource.Cancel不工作后,我读到了类似于";您的睡眠方法正在忽略CancellationToken"这种情况发生在我身上吗?
Cancellation令牌实现协同取消,这意味着代码是"取消";必须通过主动检查令牌的状态进行合作。Regex.Matches
没有接受令牌的重载,这意味着它不能以这种方式取消。
一般来说,任务不能神奇地取消。任务执行的代码必须显式地执行(使用类似token.ThrowIfCancellationRequested()
的代码(,您的代码不执行此操作,因此令牌不会执行任何有用的操作。向Task.Run
传递令牌的文档如下:
一个取消令牌,如果没有,可以用来取消工作还没有开始。Run(Action,CancellationToken(未通过cancel操作的令牌。
所以,是的,若任务并没有启动,就会取消它,这在您的情况下不太有用。
如果您执行了一些不接受和处理取消令牌的长期运行操作(并且您无法通过不时检查令牌来自己处理取消(,那么您就无法使用它们来取消它。
在你的情况下,我建议Regex.MatchTimeout