挂起任务模式:稍后再试
本文关键字:任务 模式 挂起 | 更新日期: 2023-09-27 18:26:07
我使用了几个FileSystemWatcher
对象来监视几个目录。
当我做复制&在一个被监视的文件夹上粘贴多个文件的操作,FileSystemWatcher
为我捕获的每个新创建的文件引发一个Created
事件。
我使用并发性为n的线程池,以便将作业排入队列并控制我想要在it上工作的线程数量(我可以一次创建200个文件,但我只希望有4个线程在it"表示计算校验和:
private byte[] calculateChecksum(string frl)
{
byte[] checksum = null;
FileStream stream = null;
try
{
stream = File.Open(frl, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
MD5 md5 = MD5.Create();
checksum = md5.ComputeHash(stream);
}
finally
{
stream.Close();
}
return checksum;
}
问题是,有时线程在处理该作业(calculateChecksum
方法)时,会尝试访问文件,但有时文件正在使用中(我支持SO)。
我想设置一个解决方案来解决这个问题,告诉我:"稍后再试"。
一种解决方案是,将作业再次放入线程池中。问题是我不知道以后如何告诉。我相信这很重要,因为我不希望它呼吸和休息很短时间,然后再试一次。
例如:
- 在监视文件夹上创建了新文件
FileSystemWatcher
引发一个事件- 我将作业排入线程池
- 作业崩溃,因为我想访问的文件正被另一个进程使用
- 再次将作业排队,等待60秒重试
- 60秒后,作业再次崩溃,我希望作业再次排队并等待300秒
- 300秒后,它再次尝试,并且能够正确计算校验和
我不希望这样:等待300秒意味着线程池中的一个线程正忙。它不允许调度其他排队的作业。
我不知道我是否清楚。任何想法
基本上你想要一个带定时器的重试模式。
你可以用Polly:轻松做到这一点
// Retry, waiting a specified duration between each retry
Policy
.Handle<DivideByZeroException>()
.WaitAndRetry(new[]
{
TimeSpan.FromSeconds(1),
TimeSpan.FromSeconds(2),
TimeSpan.FromSeconds(3)
});
https://github.com/App-vNext/Polly
或者像下面没有polly的一样:
https://stackoverflow.com/a/1563234/1384539