super 简单的问题,但我只是想澄清一下。我希望能够使用 AutoResetEvent 重新启动线程,因此我将以下方法序列调用到我的 AutoResetEvent。
setupEvent.Reset();
setupEvent.Set();
我知道这很明显,但 MSDN 在其文档中并未说明 Reset 方法会重新启动线程,只是将事件的状态设置为未发出信号。
更新:
是的,另一个线程正在等待 WaitOne(),我假设当它被调用时它将在它停止的确切位置恢复,这是我不想要的,我希望它从头开始重新启动.以下示例来自 this宝贵的资源说明了这一点:
static void Main()
{
new Thread (Work).Start();
_ready.WaitOne(); // First wait until worker is ready
lock (_locker) _message = "ooo";
_go.Set(); // Tell worker to go
_ready.WaitOne();
lock (_locker) _message = "ahhh"; // Give the worker another message
_go.Set();
_ready.WaitOne();
lock (_locker) _message = null; // Signal the worker to exit
_go.Set();
}
static void Work()
{
while (true)
{
_ready.Set(); // Indicate that we're ready
_go.WaitOne(); // Wait to be kicked off...
lock (_locker)
{
if (_message == null) return; // Gracefully exit
Console.WriteLine (_message);
}
}
}
如果我正确理解了这个示例,请注意主线程如何在工作线程发出信号时从它停止的地方恢复,但在我的例子中,我希望主线程从头开始重新启动。
更新 2:
@Jaroslav Jandek - 它非常复杂,但基本上我有一个 CopyDetection 线程运行 FileSystemWatcher 来监视文件夹中是否有任何新文件被移动或复制到其中。我的第二个线程负责将该特定文件夹的结构复制到另一个文件夹中。因此,我的 CopyDetection 线程必须在复制/移动操作正在进行时阻止该线程工作。操作完成后,CopyDetection 线程重新启动第二个线程,以便它可以使用新添加的文件重新复制文件夹结构。
更新 3:
@SwDevMan81 - 我实际上没有考虑过这一点,除了一个警告外,这会起作用。在我的程序中,复制过程完成后,正在复制的源文件夹将被清空。这就是为什么当新项目添加到源文件夹时我必须阻止并重新启动第二个线程,这样它就有机会正确地重新解析文件夹的新结构。
为了解决这个问题,我正在考虑添加一个标志,表明删除源文件夹的内容是安全的。我想我可以将删除操作放在它自己的清理线程上。
@Jaroslav Jandek - 抱歉,我认为随心所欲地重启线程是一件简单的事情。为了回答你的问题,我不会删除源文件夹,只是删除它的内容,这是我雇主的要求,不幸的是我不能改变。源文件夹中的文件正在移动,但不是全部,只有被另一个进程正确验证的文件,其余的必须被清除,即源文件夹被清空。此外,复制源文件夹结构的原因是某些文件包含在必须保留在目标目录中的非常严格的子文件夹层次结构中。再次抱歉让它变得复杂。所有这些机制都已经到位,已经过测试并且正在发挥作用,这就是为什么我觉得没有必要对它们进行详细说明。我只需要检测何时添加了新文件,这样我就可以在复制/移动操作正在进行时适本地停止其他进程,然后我可以安全地复制源文件夹结构并恢复处理。
最佳答案
因此线程 1 进行监控,线程 2 进行复制,而其他进程修改被监控的文件。
撇开并发文件访问不谈,您无法在更改后继续复制。因此只有在修改之间有足够长的延迟时才会成功复制。复制无法立即停止,因为您是按 block 复制的。
所以监控的结果应该是一个命令(文件复制、文件删除、文件移动等)。 成功复制的结果应该是执行命令。
考虑到可能会发生多个操作,您需要一个命令队列(或排队字典 - 仅对一个文件执行 1 个命令)。
// T1:
somethingChanged(string path, CT commandType)
{
commandQueue.AddCommand(path, commandType);
}
// T2:
while (whatever)
{
var command = commandQueue.Peek();
if (command.Execute()) commandQueue.Remove();
else // operation failed, do what you like.
}
现在您可能会问如何创建线程安全的查询,但这可能属于另一个问题(网络上有很多实现)。
EDIT(具有完整目录复制的无队列版本 - 可用于查询): 如果您不需要多个操作(例如,总是复制整个目录)并且希望复制总是完成或失败并取消,您可以这样做:
private volatile bool shouldStop = true;
// T1:
directoryChanged()
{
// StopReplicating
shouldStop = true;
workerReady.WaitOne(); // Wait for the worker to stop replicating.
// StartReplicating
shouldStop = false;
replicationStarter.Set();
}
// T2:
while (whatever)
{
replicationStarter.WaitOne();
... // prepare, throw some shouldStops so worker does not have to work too much.
if (!shouldStop)
{
foreach (var file in files)
{
if (shouldStop) break;
// Copy the file or whatever.
}
}
workerReady.Set();
}
关于c# - AutoResetEvent 重置方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5264007/