怪奇物语

怪奇物语

首页 新随笔 联系 管理

多线程,Task,线程安全队列,ConcurrentQueue,ManualResetEventSlim,文件移动

Longforce.FileMove\FileMoveApp\FileMoveApp.csproj


<Project Sdk="Microsoft.NET.Sdk">


  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

Longforce.FileMove\FileMoveApp\FileMoveTask.cs


public class FileMoveTask
{
    public string SourcePath { get; set; }
    public string DestinationPath { get; set; }
}

Longforce.FileMove\FileMoveApp\Program.cs


using System;
using System.Collections.Concurrent;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    private static readonly string SourceDirectory = @"D:\inetpub\wwwroot\Mes\szaddon\szpH060\HSLPAD";

    // @"D:\inetpub\wwwroot\Mes\szaddon\szpH060\HSLPAD";
    // @"D:\inetpub\wwwroot\Mes\szaddon\szpH060\Picture";
    // @"D:\inetpub\wwwroot\Mes\szaddon\szpH060\OQC_reports";

    private static readonly string DestinationDirectory = @"Z:\inetpub\wwwroot\Mes\szaddon\szpH060\HSLPAD";
    private static readonly ConcurrentQueue<FileMoveTask> FileMoveQueue = new ConcurrentQueue<FileMoveTask>();
    private static readonly CancellationTokenSource CancellationTokenSource = new CancellationTokenSource();
    private static readonly ManualResetEventSlim AllFilesProcessed = new ManualResetEventSlim(false);
    private static int _totalFiles = 0;
    private static int _completedFiles = 0;
    private static readonly object _lockObject = new object();

    static void Main()
    {
        Console.WriteLine("开始准备移动文件...");
        try
        {
            // 检查源目录是否存在
            if (!Directory.Exists(SourceDirectory))
            {
                Console.WriteLine($"错误: 源目录 {SourceDirectory} 不存在。");
                return;
            }
            // 创建目标目录(如果不存在)
            Directory.CreateDirectory(DestinationDirectory);
            // 扫描源目录并准备移动任务
            Console.WriteLine("正在扫描文件...");
            ScanDirectory(SourceDirectory);
            Console.WriteLine($"已扫描完成,共找到 {_totalFiles} 个文件。");

            if (_totalFiles == 0)
            {
                Console.WriteLine("没有文件需要移动。");
                return;
            }

            // 启动进度显示线程
            var progressThread = new Thread(ShowProgress);
            progressThread.IsBackground = true;
            progressThread.Start();

            // 启动多个工作线程
            const int maxThreads = 8;
            var tasks = new Task[maxThreads];

            for (int i = 0; i < maxThreads; i++)
            {
                tasks[i] = Task.Run(() => ProcessFileMoveQueue(CancellationTokenSource.Token));
            }

            // 等待所有任务完成
            Task.WaitAll(tasks);
            AllFilesProcessed.Wait();

            Console.WriteLine("\n所有文件移动完成!");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"\n发生致命错误: {ex.Message}");
        }
        finally
        {
            CancellationTokenSource.Cancel();
            AllFilesProcessed.Dispose();
        }

        Console.WriteLine("按任意键退出...");
        Console.ReadKey();
    }

    private static void ScanDirectory(string sourcePath)
    {
        try
        {
            // 获取当前目录下的所有文件
            string[] files = Directory.GetFiles(sourcePath);

            foreach (string file in files)
            {
                string relativePath = Path.GetRelativePath(SourceDirectory, file);
                string destinationPath = Path.Combine(DestinationDirectory, relativePath);

                // 创建目标目录(如果不存在)
                string destinationDir = Path.GetDirectoryName(destinationPath);
                Directory.CreateDirectory(destinationDir);

                // 添加到移动队列
                FileMoveQueue.Enqueue(new FileMoveTask { SourcePath = file, DestinationPath = destinationPath });

                Interlocked.Increment(ref _totalFiles);
            }

            // 递归处理子目录
            string[] directories = Directory.GetDirectories(sourcePath);
            foreach (string directory in directories)
            {
                ScanDirectory(directory);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"扫描目录时出错 ({sourcePath}): {ex.Message}");
        }
    }

    private static void ProcessFileMoveQueue(CancellationToken cancellationToken)
    {
        while (!cancellationToken.IsCancellationRequested)
        {
            if (FileMoveQueue.TryDequeue(out FileMoveTask task))
            {
                try
                {
                    MoveFileWithRetry(task.SourcePath, task.DestinationPath);
                    Interlocked.Increment(ref _completedFiles);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"移动文件时出错 ({task.SourcePath} -> {task.DestinationPath}): {ex.Message}");
                }
            }
            else if (_completedFiles == _totalFiles)
            {
                AllFilesProcessed.Set();
                break;
            }
            else
            {
                // 队列暂时为空,等待片刻
                Thread.Sleep(100);
            }
        }
    }

    private static void MoveFileWithRetry(string sourcePath, string destinationPath, int maxRetries = 3)
    {
        int retries = 0;

        while (true)
        {
            try
            {
                // 如果目标文件已存在,删除原来路径的文件
                if (File.Exists(destinationPath))
                {
                    File.Delete(sourcePath);
                    break;
                }
                // 移动文件
                File.Move(sourcePath, destinationPath, false);
                // 验证文件是否成功移动
                if (!File.Exists(destinationPath))
                {
                    throw new IOException("文件移动后不存在于目标位置");
                }
                break;
            }
            catch (Exception ex)
            {
                retries++;
                if (retries > maxRetries)
                {
                    Console.WriteLine($"文件移动失败 ({sourcePath} -> {destinationPath}): {ex.Message}");
                    throw;
                }
                // 等待一段时间后重试
                Thread.Sleep(500 * retries);
            }
        }
    }

    private static void ShowProgress()
    {
        while (!AllFilesProcessed.IsSet)
        {
            lock (_lockObject)
            {
                Console.CursorLeft = 0;
                Console.Write($"进度: {_completedFiles}/{_totalFiles} 文件 ({_completedFiles * 100.0 / Math.Max(1, _totalFiles):F2}%)");
            }
            Thread.Sleep(500);
        }
    }
}

Longforce.FileMove\.csharpierrc.json


{
  "printWidth": 200,
  "useTabs": false,
  "tabWidth": 4,
  "endOfLine": "auto"
}

Longforce.FileMove\global.json


{
  "sdk": {
    "version": "6.0.427"
  }
}

Longforce.FileMove\Longforce.FileMove.sln



Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileMoveApp", "FileMoveApp\FileMoveApp.csproj", "{F1B9D848-52A3-4C75-8D86-A13C597AD7A7}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Debug|x64 = Debug|x64
		Debug|x86 = Debug|x86
		Release|Any CPU = Release|Any CPU
		Release|x64 = Release|x64
		Release|x86 = Release|x86
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{F1B9D848-52A3-4C75-8D86-A13C597AD7A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{F1B9D848-52A3-4C75-8D86-A13C597AD7A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{F1B9D848-52A3-4C75-8D86-A13C597AD7A7}.Debug|x64.ActiveCfg = Debug|Any CPU
		{F1B9D848-52A3-4C75-8D86-A13C597AD7A7}.Debug|x64.Build.0 = Debug|Any CPU
		{F1B9D848-52A3-4C75-8D86-A13C597AD7A7}.Debug|x86.ActiveCfg = Debug|Any CPU
		{F1B9D848-52A3-4C75-8D86-A13C597AD7A7}.Debug|x86.Build.0 = Debug|Any CPU
		{F1B9D848-52A3-4C75-8D86-A13C597AD7A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{F1B9D848-52A3-4C75-8D86-A13C597AD7A7}.Release|Any CPU.Build.0 = Release|Any CPU
		{F1B9D848-52A3-4C75-8D86-A13C597AD7A7}.Release|x64.ActiveCfg = Release|Any CPU
		{F1B9D848-52A3-4C75-8D86-A13C597AD7A7}.Release|x64.Build.0 = Release|Any CPU
		{F1B9D848-52A3-4C75-8D86-A13C597AD7A7}.Release|x86.ActiveCfg = Release|Any CPU
		{F1B9D848-52A3-4C75-8D86-A13C597AD7A7}.Release|x86.Build.0 = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
EndGlobal

Longforce.FileMove\VERSION.md




```sh



dotnet publish .\FileMoveApp\FileMoveApp.csproj -c Release -r win-x64 --self-contained true /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true -o .\Publish\FileMoveApp\V1.0.0
dotnet publish .\FileMoveApp\FileMoveApp.csproj -c Release -r win-x64 --self-contained true /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true -o .\Publish\FileMoveApp\V2.0.0
dotnet publish .\FileMoveApp\FileMoveApp.csproj -c Release -r win-x64 --self-contained true /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true -o .\Publish\FileMoveApp\V3.0.0



posted on 2025-07-10 08:00  超级无敌美少男战士  阅读(15)  评论(0)    收藏  举报