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
相关产品推荐
相关产品推荐

