Reputation: 153
I am creating console app to simulate server. I create multiple virus files together using multiple threads to see whether all files get quarantined, if yes, how long it takes to quarantined. The problem with multithreading application is one thread starts writing another thread so I get exception - The process can not access the file X because the file is being used by another process. This is the reason that all files don't get quarantined. I use framework 4.5.2 I have created app using thread and task. I don't get the desire result. What is the best practice to write this app? Thank you for helping me in advance.
Using Thread:
class Program
{
static string folderPath;
static readonly string fileContent = @"X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*";
static void Main(string[] args)
{
folderPath = "F:\VirusScan";
int counter = 1000;
for (int i = 0; i < counter; i++)
{
var thread = new Thread(() => GenerateVirusFile(i));
thread.Start();
}
Console.ReadKey();
}
static void GenerateVirusFile(int i)
{
string filePath = $@"{folderPath}\TestForVirusScan_{i}_{DateTime.Now.ToString("yyyyMMddHHmmssffff")}.txt";
try
{
using (StreamWriter writer = new StreamWriter(filePath))
{
writer.WriteLine(fileContent);
}
var timer = Stopwatch.StartNew();
while (true)
{
if (!File.Exists(filePath))
{
Console.WriteLine($"{i}: File was removed in {timer.ElapsedMilliseconds}ms");
break;
}
else
{
Thread.Sleep(1);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"{i}: Exception {ex.GetType().Name} occurred: {ex.Message}");
}
}
}
Using Task:
class Program
{
static string folderPath;
static readonly string fileContent = @"X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*";
static void Main(string[] args)
{
folderPath = "F:\VirusScan";
int counter = 1000;
List<Task> tasks = new List<Task>();
for (int i = 1; i <= counter; i++)
{
Task newTask = new Task((x) => GenerateVirusFile(x), i);
tasks.Add(newTask);
}
foreach (var task in tasks)
{
task.Start();
}
Task.WaitAll(tasks.ToArray());
Console.ReadKey();
}
public static void GenerateVirusFile(object i)
{
string filePath = $@"{folderPath}\TestForVirusScan_{i}_{DateTime.Now.ToString("yyyyMMddHHmmssffff")}.txt";
try
{
using (StreamWriter writer = new StreamWriter(filePath))
{
writer.WriteLine(fileContent);
}
var timer = Stopwatch.StartNew();
while (true)
{
if (!File.Exists(filePath))
{
Console.WriteLine($"{i}: File was removed in {timer.ElapsedMilliseconds}ms");
break;
}
else
{
Thread.Sleep(1);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"{i}: Exception {ex.GetType().Name} occurred: {ex.Message}");
}
}
}
Upvotes: 1
Views: 1899
Reputation: 929
The problem is in the following code:
for (int i = 0; i < counter; i++)
{
var thread = new Thread(() => GenerateVirusFile(i));
thread.Start();
}
The closure () => GenerateVirusFile(i)
is referencing changing variable
Rewrite it in the following way:
Parallel.For(0, counter, GenerateVirusFile);
Upvotes: 1
Reputation:
Have you tried something like this in your loop:
int x = i;
var thread = new Thread(() => GenerateVirusFile(x));
this prevents that the same i
is used for more threads/file names.
Upvotes: 0