Example #1
0
            // Handle the next file in the enumeration.
            private void EnumerateNextFile(EnumerableWrapper wrapper)
            {
                LogicalThread enumerationThread;
                Action enumerateNextFile;
                string file;

                try
                {
                    while (true)
                    {
                        // Advance enumeration until the
                        // next file that matches the filter
                        if (!wrapper.MoveNext())
                            return;

                        if (m_fileProcessor.MatchesFilter(wrapper.Current))
                            break;

                        Interlocked.Increment(ref m_fileProcessor.m_skippedFileCount);
                    }

                    // Prepare the callback to return execution to this thread
                    enumerationThread = LogicalThread.CurrentThread;
                    enumerateNextFile = () => EnumerateNextFile(wrapper);
                    file = wrapper.Current;

                    // Kick off the operation to process the current file,
                    // but don't enumerate to the next file until processing
                    // for the current file has begun
                    m_fileProcessor.m_processingThread.Push(1, () =>
                    {
                        // Check the state of cancellation for the
                        // enumeration thread on the processing
                        // thread as well to speed up cancellation
                        if (wrapper.CancellationToken.IsCancelled)
                        {
                            enumerationThread.Push(DeactivateThread);
                            return;
                        }

                        enumerationThread.Push(enumerateNextFile);
                        m_fileProcessor.TouchLockAndProcess(file);
                    });
                }
                catch
                {
                    // If an exception occurs,
                    // dispose of the enumerable wrapper
                    wrapper.Dispose();
                    throw;
                }
                finally
                {
                    // If there are no more files to enumerate,
                    // dispose of the wrapper and move to the next wrapper
                    if (!wrapper.LastMove)
                    {
                        wrapper.Dispose();
                        EnumerateNextWrapper();
                    }
                }
            }
Example #2
0
            // Handle the next directory in the enumeration.
            private void EnumerateNextDirectory(EnumerableWrapper wrapper)
            {
                EnumerableWrapper fileWrapper;
                EnumerableWrapper directoryWrapper;
                string directory;

                try
                {
                    // Advance directory enumeration
                    if (!wrapper.MoveNext())
                    {
                        // No more directories, so dispose
                        // and then move to the next wrapper
                        wrapper.Dispose();
                        EnumerateNextWrapper();
                        return;
                    }

                    // Initialize the fileWrapper
                    // and directoryWrapper
                    directory = wrapper.Current;
                    fileWrapper = null;
                    directoryWrapper = null;
                }
                catch
                {
                    // If an error occurs, dispose of the
                    // wrapper and then move to the next wrapper
                    wrapper.Dispose();
                    EnumerateNextWrapper();
                    throw;
                }

                try
                {
                    switch (m_fileProcessor.EnumerationStrategy)
                    {
                        // Sequential and ParallelWatchDirectories strategies
                        // place subdirectories on the current thread
                        case FileEnumerationStrategy.Sequential:
                        case FileEnumerationStrategy.ParallelWatchDirectories:
                            // Create the fileWrapper and directoryWrapper objects
                            fileWrapper = new EnumerableWrapper(Directory.EnumerateFiles(directory), wrapper.CancellationToken);
                            directoryWrapper = new EnumerableWrapper(Directory.EnumerateDirectories(directory), wrapper.CancellationToken);

                            // Push the current directory wrapper onto the stack
                            m_wrapperStack.Value.Push(() => EnumerateNextDirectory(wrapper));

                            // Push the subdirectory's file wrapper onto the stack
                            m_wrapperStack.Value.Push(() => EnumerateNextFile(fileWrapper));

                            // Continue enumeration with the directory wrapper for the subdirectory
                            LogicalThread.CurrentThread.Push(() => EnumerateNextDirectory(directoryWrapper));
                            break;

                        // ParallelSubdirectories strategy spawns new threads for subdirectories
                        case FileEnumerationStrategy.ParallelSubdirectories:
                            // Create the fileWrapper and directoryWrapper objects
                            fileWrapper = new EnumerableWrapper(Directory.EnumerateFiles(directory), wrapper.CancellationToken);
                            directoryWrapper = new EnumerableWrapper(Directory.EnumerateDirectories(directory), wrapper.CancellationToken);

                            // Create a new thread, push the file wrapper onto the new thread's
                            // stack, then enumerate the directory wrapper on the new thread
                            m_fileProcessor.m_threadScheduler.CreateThread().Push(() =>
                            {
                                ActivateThread();
                                m_wrapperStack.Value.Push(() => EnumerateNextFile(fileWrapper));
                                EnumerateNextDirectory(directoryWrapper);
                            });

                            // Continue enumeration on this thread with the current directory wrapper
                            LogicalThread.CurrentThread.Push(() => EnumerateNextDirectory(wrapper));
                            break;

                        // The only other file enumeration
                        // strategy is no strategy at all
                        default:
                            // Clear out the stack and queue,
                            // then dispose of the wrapper
                            m_wrapperStack.Value.Clear();
                            m_directoryQueue.Value.Clear();
                            wrapper.Dispose();
                            DeactivateThread();
                            break;
                    }
                }
                catch
                {
                    // If an exception occurs, dispose of the file
                    // wrapper and directory wrapper, then continue
                    // enumeration with the current directory wrapper
                    if ((object)fileWrapper != null)
                        fileWrapper.Dispose();

                    if ((object)directoryWrapper != null)
                        directoryWrapper.Dispose();

                    LogicalThread.CurrentThread.Push(() => EnumerateNextDirectory(wrapper));

                    throw;
                }
            }