You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#多线程磁盘监控异常:线程无法终止及变量冲突求助

多磁盘场景下磁盘监控程序的变量复用问题

我是C#新手,编写了一款磁盘监控程序,当检测到写入超时或磁盘断开等异常时将重启计算机。程序通过以下代码遍历计算机磁盘:

foreach (var drive in DriveInfo.GetDrives())
{
    if (drive.IsReady == true)
    {
        double totalSpace = drive.TotalSize;
        int totalSpaceinGB = (int)(totalSpace / 1024 / 1024 / 1024);

        if (totalSpaceinGB > diskThresholdGb)
        {
            string diskName = drive.Name;
            Console.WriteLine(diskName);

            Console.WriteLine("we start");
            Thread t = new Thread(Listener);
            t.Start(diskName);
        }
    }
}

为每个符合条件的磁盘启动独立Thread,传入磁盘名称作为参数。单磁盘场景下程序运行正常,但多磁盘场景中,当从磁盘管理器离线某一磁盘后,程序出现变量复用问题,其他磁盘也会触发超时和错误。我怀疑问题出在Listener方法中的以下变量:

int failedCounter = 0;
bool exceptionFlag = false;

以下是完整代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Threading;
using System.Timers;
using System.Collections;


public class Example
{
    //public static int failedCounter = 0;
    public static int errorRestartThreshold = 5;


    const int delayInMilliseconds = 1000;
    const int diskThresholdGb = 20;
    const string writeDirectoryName = "cdiskmonitorCheck";
    const string writeFileName = "cdiskmonitorCheck.txt";

    const string fullErrorDirectoryName = "c:\\cdiskmonitorCheck";
    const string fullErrorFileName = fullErrorDirectoryName + "\\" + "cdiskmonitorError.log";



    //public bool exceptionFlag = false;

    public static void Main()
    {
        Example e = new Example();
        e.OnStart();

    }
    public void OnStart()
    {

        //Thread t = new Thread(Listener);
        foreach (var drive in DriveInfo.GetDrives())
        {
            if (drive.IsReady == true)
            {
                double totalSpace = drive.TotalSize;
                int totalSpaceinGB = (int)(totalSpace / 1024 / 1024 / 1024);

                if (totalSpaceinGB > diskThresholdGb)
                {
                    string diskName = drive.Name;
                    Console.WriteLine(diskName);

                    Console.WriteLine("we start");
                    Thread t = new Thread(Listener);
                    t.Start(diskName);


                }
            }

        }
        Console.ReadLine();

    }

    private void Listener(object diskLetter)
    {
        Thread thread = null;

        //diskLetter = "fff:";

        int failedCounter = 0;
        bool exceptionFlag = false;

        string fullWriteFolderPath = diskLetter + writeDirectoryName;
        string fullWriteFilePath = fullWriteFolderPath + "\\" + writeFileName;

        while (true)
        {
            var task = Task.Run(() =>
            {

                Console.WriteLine($@"-----------------------------------------------Thread {diskLetter} ----------------------------------------------------");
                exceptionFlag = false;
                DateTime start = DateTime.Now;
                thread = Thread.CurrentThread;

                try
                {
                    //create directory
                    if (!Directory.Exists(fullWriteFolderPath))
                    {
                        Directory.CreateDirectory(fullWriteFolderPath);
                    }
                    //Console.WriteLine(fullWriteFilePath);

                    //                    Console.WriteLine(start.ToString("MM/dd/yyyy hh:mm:ss.fff"));
                    using (StreamWriter sw = new StreamWriter(fullWriteFilePath))
                    {
                        sw.WriteLine(start.ToString("MM/dd/yyyy hh:mm:ss.fff"));
                    }

                    failedCounter = 0;
                }
                catch (Exception ex)
                {
                    exceptionFlag = true;
                    //break;
                    Console.WriteLine(ex.ToString());

                }

                DateTime finish = DateTime.Now;

                System.TimeSpan diff = finish - start;
                int diffInMilliseconds = (int)diff.TotalMilliseconds;

                //we wait for sometime to be 1 second
                if (diffInMilliseconds < delayInMilliseconds)
                {
                    Task.Delay((delayInMilliseconds - diffInMilliseconds)).Wait();
                    //Console.WriteLine((delayInMilliseconds - diffInMilliseconds));
                }

            });


            //Check if task is finished.

            bool isCompletedSuccessfully = task.Wait(TimeSpan.FromMilliseconds(1200));


            //Console.WriteLine(isCompletedSuccessfully);
            DateTime current = DateTime.Now;
            if (!Directory.Exists(fullErrorDirectoryName))
            {
                Directory.CreateDirectory(fullErrorDirectoryName);
            }

            if (exceptionFlag)
            {
                current = DateTime.Now;
                thread.Abort(true);
                failedCounter++;
                Console.WriteLine("Exception writting to file");
                using (StreamWriter sw = File.AppendText(fullErrorFileName))
                {
                    sw.WriteLine(current.ToString("MM/dd/yyyy hh:mm:ss.fff") + " exception, counter:" + failedCounter.ToString());
                }
            }
            else
            {
                if (!isCompletedSuccessfully)
                {

                    current = DateTime.Now;
                    failedCounter++;
                    Console.WriteLine("Timeoutted writting to file");
                    thread.Abort(true);

                    using (StreamWriter sw = File.AppendText(fullErrorFileName))
                    {
                        sw.WriteLine(current.ToString("MM/dd/yyyy hh:mm:ss.fff") + " timeoutted, counter:" + failedCounter.ToString());
                    }

                }
                else
                {
                    failedCounter = 0;
                    Console.WriteLine($@"Task completed during period. Thread {diskLetter}");
                }

            }

            Console.WriteLine($@"Thread {diskLetter}, fails count:{failedCounter}");



            if (failedCounter >= errorRestartThreshold)
            {
                current = DateTime.Now;
                using (StreamWriter sw = File.AppendText(fullErrorFileName))
                {
                    sw.WriteLine(current.ToString("MM/dd/yyyy hh:mm:ss.fff") + " we restart server., counter:" + failedCounter.ToString());
                }
            }


        }

    }

}

内容的提问来源于stack exchange,提问作者Юрий XXX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 23:37:05