create multiple files using multiple threads c# - c#

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}");
}
}
}

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);

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.

Related

How to create new file only after 5 minutes and write all 5 minutes data into that file

I am generating data every 1 second to write in a file but I want a new file every 5 minutes rather than every 1 second and want to writes all 5 minutes data into that file.
Below code generate a new file every 1 second and for that period data writes in the file. How I can generate a new file every 5 minutes?
static void Main(string[] args)
{
var incremental = 0;
while (true)
{
Go(incremental);
incremental++;
Thread.Sleep(1000);
}
}
private static void Go(int incremental)
{
var fileFullPath = GetDynamicFullPath(#"C:\Temp\");
using var rewrite = new StreamWriter(fileFullPath);
rewrite.WriteLine(incremental);
}
private static string GetDynamicFullPath(string basePath)
{
var dynamicFileName = $"file-{DateTime.Now:yyyyMMddHHmmssfff}.txt";
return basePath + dynamicFileName;
}
This is exactly the case where the .Net Reactive library (System.Reactive) shines.
Install it via NuGet package maneger, then the code will look like this:
1:declare buffer variable:
private readonly Subject<int> _myBuffer = new Subject<int>();
2:setup buffer subscription
_myBuffer.Buffer(TimeSpan.FromMinutes(5))
.Subscribe(bufferData => Go(bufferData.ToArray()));
3:your Do method is little changed to accept array of ints
private void Go(int[] bufferData)
{
var fileFullPath = GetDynamicFullPath(#"C:\Temp\");
using var rewrite = new StreamWriter(fileFullPath);
rewrite.WriteLine(bufferData);
}
4:finally, the infinite loop
var incremental = 0;
while (true)
{
_myBuffer.OnNext(incremental++);
Thread.Sleep(1000);
}
It can not be simpler!
The point is that Buffer method will automatically collect all received data for the specified period. You just need to subscribe to it (start listening to it) and then your `Do' method will be executed every 5 minutes with the buffered data.
I would suggest the simplest solution:
You can store a datetime when the last file was created.
You can also define a 5 mins threshold.
You should call the file create method when the current datetime is greater than the sum of the last created timestamp and the threshold.
Sample code:
private static readonly TimeSpan threshold = TimeSpan.FromMinutes(5);
private static DateTime lastCreated = DateTime.UtcNow;
public static void Main()
{
while(true)
{
if(DateTime.UtcNow >= lastCreated.Add(threshold))
{
//call the file create method
lastCreated = DateTime.UtcNow;
}
Thread.Sleep(1000);
}
}
I would advice you to use a Timer to flush and create the files all 5 Minutes. You then also should use a SemaphoreSlim to synchronize the access to the StreamWriter, because the callback for the timer may be executed on any Thread-Pool-Thread.
So I would do something like:
public static StreamWriter writer;
public static SemaphoreSlim mutex;
static void Main(string[] args)
{
mutex = new SemaphoreSlim(1,1);
var incremental = 0;
using var timer = new Timer(5 * 60 * 1000);
static void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
CreateNewFile();
}
timer.Elapsed += Timer_Elapsed;
timer.AutoReset = true;
timer.Start();
while (true)
{
WriteData(incremental);
Thread.Sleep(1000);
incremental++;
}
}
private static void WriteData(int data)
{
mutex.Wait();
try
{
// write you data ...
}
finally
{
mutex.Release();
}
}
private static void CreateNewFile()
{
mutex.Wait();
try
{
if (writer != null)
{
writer.Dispose();
writer = null;
}
var fileFullPath = GetDynamicFullPath(#"C:\Temp\");
writer = new StreamWriter(fileFullPath);
}
finally
{
mutex.Release();
}
}
private static string GetDynamicFullPath(string basePath)
{
var dynamicFileName = $"file-{DateTime.Now:yyyyMMddHHmmssfff}.txt";
return basePath + dynamicFileName;
}
In addition I would suggest to use the async versions of all these methodes. So WaitAsync(), WriteLineAsync, ...
public static StreamWriter writer;
public static SemaphoreSlim mutex;
static async Task Main(string[] args)
{
mutex = new SemaphoreSlim(1, 1);
var incremental = 0;
using var timer = new Timer(5 * 60 * 1000);
static async void Timer_ElapsedAsync(object sender, ElapsedEventArgs e)
{
await CreateNewFileAsync();
}
timer.Elapsed += Timer_ElapsedAsync;
timer.AutoReset = true;
timer.Start();
while (true)
{
await WriteDataAsync(incremental);
await Task.Delay(1000);
incremental++;
}
}
private static async Task WriteDataAsync(int data)
{
await mutex.WaitAsync();
try
{
// write you data ...
await writer.WriteLineAsync(data.ToString());
}
finally
{
mutex.Release();
}
}
private static async Task CreateNewFileAsync()
{
await mutex.WaitAsync();
try
{
if (writer != null)
{
await writer.DisposeAsync();
writer = null;
}
var fileFullPath = GetDynamicFullPath(#"C:\Temp\");
writer = new StreamWriter(fileFullPath);
}
finally
{
mutex.Release();
}
}
private static string GetDynamicFullPath(string basePath)
{
var dynamicFileName = $"file-{DateTime.Now:yyyyMMddHHmmssfff}.txt";
return basePath + dynamicFileName;
}

parallel read/process/write stop working without any exception

I have to read a file and after processing it's data write result to another file. This process takes too much time so I tried to do read/process/write in a parallel way. Code works well. But there is a problem, when I was testing it for processing very huge file (100GB) after about 40GB program stops working. It do not throw any exception (except 'TimeoutException'). I spend several days and tried to change many things. I know it is not about method or memory. But I am really confused about reason and way to make it works well.
Note: I wanted to post this on Code Review, but Code Review rules says do not post for trouble shooting and else so I posted it here.
The way I use code (It is on backgroundworker)
BackgroundWorker worker = (BackgroundWorker)sender;
ReaderWriterMultiThread readerWriterMultiThread = null;
int bufferSize = 2 * 1024 * 1024;
int readerWriterMultiThreadPartsNumber = 10;
int sizeToReadInThisIteration = 0;
int oldprecentage = 0;
long fileDid = 0;
using (FileStream streamReader = new FileStream(fromAddress, FileMode.Open))
using (BinaryReader binaryReader = new BinaryReader(streamReader))
using (FileStream streamWriter = new FileStream(toAddress, FileMode.Open))
using (BinaryWriter binaryWriter = new BinaryWriter(streamWriter))
{
sizeToReadInThisIteration = bufferSize * readerWriterMultiThreadPartsNumber;
streamWriter.Seek(0, SeekOrigin.Begin);
while (streamWriter.Position < length)
{
if (worker.CancellationPending)
{
e.Cancel = true;
return;
}
//change sizeToReadInThisIteration if needs
if (streamWriter.Position + sizeToReadInThisIteration > length)
{ sizeToReadInThisIteration = Convert.ToInt32(length - streamWriter.Position); }
//new it
readerWriterMultiThread = new ReaderWriterMultiThread();
//read/do/write
readerWriterMultiThread.Start(binaryReader, binaryWriter, bufferSize, sizeToReadInThisIteration,
(ref byte[] bytes) => DoNothing(ref bytes));
//report process if needs
fileDid += sizeToReadInThisIteration;
if (((int)(fileDid * 100 / length)) > oldprecentage)
{
oldprecentage = (int)(fileDid * 100 / length);
worker.ReportProgress(oldprecentage);
}
}//while
}//using
DoNothing method is:
public void DoNothing(ref byte[] bufferToCode)
{ }
and ReaderWriterMultiThread class is:( Originally code used threads but I changed it to use tasks.)
public class ReaderWriterMultiThread
{
#region variables
//buffer(contain several part)
List<byte[]> buffer = new List<byte[]>();
//lock objects
private object bufferLockForRead = new object();
private object bufferLockForWrite = new object();
//indexes
int readIndex = 0;
int doReadIndex = 0;
int doWriteIndex = 0;
int writeIndex = 0;
//complete vars
int lastIndex = int.MaxValue;
bool readCompleted = false;
//waiting properties
private bool doIsWaiting = false;
private bool writerIsWaiting = false;
//error properties
private bool anyErrorHappend = false;
private string errorsMessage = string.Empty;
//proc delegate
public delegate void DelegateMethod(ref byte[] bytes);
//proc delegate instance
DelegateMethod delegateM;
//
#endregion variables
//==============================
#region methods
//
public void Start(BinaryReader binaryReader, BinaryWriter binaryWriter, int bufferPartsSize, int size, DelegateMethod delegateMethod)
{
//new delegate
delegateM = new DelegateMethod(delegateMethod);
//for wait all
Task[] tasks = new Task[3];
//run
var parentTask = Task.Factory.StartNew(() =>
{
tasks[0] = Task.Factory.StartNew(() =>
{
Writer(binaryWriter);
});
tasks[1] = Task.Factory.StartNew(() =>
{
Do();
});
tasks[2] = Task.Factory.StartNew(() =>
{
Reader(binaryReader, bufferPartsSize, size);
});
});
//wait
parentTask.Wait();
if (!Task.WaitAll(tasks, 10000))
{ throw new TimeoutException(); }
if (anyErrorHappend)
{ throw new Exception(errorsMessage); }
}
private void AddByReader(byte[] newBytes, bool completed)
{
try
{
lock (bufferLockForRead)
{
//add data to buffer
buffer.Add(newBytes);
//updare readIndex
readIndex++;
//if completed show it
if (completed)
{
readCompleted = true;
lastIndex = buffer.Count;//it uses as <lastIndex (so lastIndex = buffer.Count is ok)
}
//manage happend error
if (anyErrorHappend)
{
readCompleted = true;
lastIndex = doReadIndex + 1;
}
//if do is waiting pulse it
if (doIsWaiting)
{ Monitor.Pulse(bufferLockForRead); }
}
}
catch (Exception ex)
{ Debug.Assert(false, ex.ToString()); }
}
private byte[] GetByDo()
{
try
{
lock (bufferLockForRead)
{
//if data did not read already wait
if (doReadIndex == readIndex)
{
doIsWaiting = true;
Monitor.Wait(bufferLockForRead);
}
//do is not waiting now
doIsWaiting = false;
//in case of emergency
if (doReadIndex > readIndex)
{ return new byte[0]; }
//return
return buffer[doReadIndex++];
}
}
catch (Exception ex)
{
Debug.Assert(false, ex.ToString());
return new byte[0];
}
}
private void AddByDo(byte[] newBytes, string errorMessageFromDO)
{
try
{
lock (bufferLockForWrite)
{
//add data
buffer[doWriteIndex] = newBytes;
//update doWriteIndex
doWriteIndex++;
//error happend in Do
if (errorMessageFromDO.Length > 0)
{
anyErrorHappend = true;
errorsMessage += errorMessageFromDO;
lastIndex = -1;
Monitor.Pulse(bufferLockForWrite);
}
//if reader completed and writer is in wait state pulse it
if (readCompleted && writerIsWaiting)
{
Monitor.Pulse(bufferLockForWrite);
}
}
}
catch (Exception ex)
{ Debug.Assert(false, ex.ToString()); }
}
private byte[] GetByWriter()
{
try
{
lock (bufferLockForWrite)
{
//if data did not proccessed wait
if (writeIndex == doWriteIndex)
{
writerIsWaiting = true;
Monitor.Wait(bufferLockForWrite);
}
//writer is not waithing
writerIsWaiting = false;
//return
return buffer[writeIndex++];
}
}
catch (Exception ex)
{
Debug.Assert(false, ex.ToString());
return new byte[0];
}
}
private void Reader(BinaryReader binaryReader, int bufferPartSize, int sizeToRead)
{
try
{
//vars
bool completed = false;
int readedSize = 0;
byte[] readedBytes = new byte[0];
while (readedSize < sizeToRead && !anyErrorHappend)
{
//change bufferPartSize & completed if needs
if (readedSize + bufferPartSize >= sizeToRead)
{
bufferPartSize = sizeToRead - readedSize;
completed = true;
}
try
{
//read
readedBytes = binaryReader.ReadBytes(bufferPartSize);
}
catch (Exception ex)
{
Debug.Assert(false, ex.ToString());
//error happend
anyErrorHappend = true;
errorsMessage += ex.Message;
//for pulse Do() if it is waiting
byte[] amptyBytesArray = new byte[0];
AddByReader(amptyBytesArray, true);//it is better to do it instead change lastIndex here
break;
}
//add to buffer
AddByReader(readedBytes, completed);
//update readedSize
readedSize += bufferPartSize;
}
}
catch (Exception ex)
{ Debug.Assert(false, ex.ToString()); }
}
private void Writer(BinaryWriter binaryWriter)
{
try
{
//vars
byte[] bytesToWrite = new byte[0];//for put getted data in
for (int i = 0; i < lastIndex; i++)
{
//get data from buffer
bytesToWrite = GetByWriter();
try
{
//write
binaryWriter.Write(bytesToWrite);
}
catch (Exception ex)
{
Debug.Assert(false, ex.ToString());
lastIndex = -1;
anyErrorHappend = true;
errorsMessage = ex.Message;
break;
}
}
}
catch (Exception ex)
{ Debug.Assert(false, ex.ToString()); }
}
private void Do()
{
try
{
//vars
byte[] bytes = new byte[0];//for put readed data/result in
for (int i = 0; i < lastIndex; i++)
{
//get data from buffer
bytes = GetByDo();
try
{
//do
delegateM(ref bytes);
}
catch (Exception ex)
{
Debug.Assert(false, ex.ToString());
//add
AddByDo(new byte[0], "error: " + ex.Message);
break;
}
//add data to buffer
AddByDo(bytes, string.Empty);
}
}
catch (Exception ex)
{ Debug.Assert(false, ex.ToString()); }
}
//
#endregion methods
}
You code is throwing an exception here:
if (!Task.WaitAll(tasks, 10000))
{ throw new TimeoutException(); }
Which means that one of your tasks is taking more than 10 seconds to complete.
This could be because it needs more time. It could also be because one of your tasks is getting stuck waiting to enter a lock. It could also because the Monitor.Wait is getting stuck waiting for a lock.
You can add logging to see where it is getting hung. Additionally if one of your assert statements fail it will prevent a task from completing in time.
As a side note, Disk IO is time consuming and in general trying to parallelize IO operations like this typically aren't going to help because the threads end up stomping all over each other contending for disk access time. The disk ends up needing to spin to numerous positions back and forth to read and write data and you end up with a net effect of actually slowing things down. You might be able to speed things up if you are using RAID or you are reading from one disk and adding the reads to a queue and your write thread is reading from that queue and writing that data to a different disk.

Can "ThrowIfCancellationRequested" not be caught by TaskScheduler_UnobservedTaskException?

I have a very very strange problem, and here's my codes now:
namespace TaskParallelTest
{
using System.Threading;
using System.Threading.Tasks;
using System;
using System.IO;
public class Program
{
static Program()
{
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
}
private static void DoPrint(int id, CancellationToken cToken)
{
Thread.Sleep(100);
if (!cToken.IsCancellationRequested)
{
Console.WriteLine("Id is:" + id + ";Current State:" + cToken.IsCancellationRequested);
cToken.Register(() => Console.WriteLine("Rollback for:" + id));
}
}
static void Main(string[] args)
{
CancellationTokenSource cTokenSource = new CancellationTokenSource();
Task.Run(() =>
{
for (int i = 1; i < 6; i++)
{
cTokenSource.Token.ThrowIfCancellationRequested();
DoPrint(i, cTokenSource.Token);
}
}, cTokenSource.Token);
Random r = new Random();
Thread.Sleep(400);
cTokenSource.Cancel(true);
Thread.Sleep(10000);
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("OK");
Console.ReadLine();
}
private static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
File.WriteAllText("C:\\Resume\\Error.txt", e.Exception.StackTrace);
e.SetObserved();
}
}
}
What makes me feel mad is why the event of "UnobservedTaskException" cannot be caught? I used GC.Collect() and Thread.Sleep(), but without any help……?
Sometimes, the "Error.txt" wasn't created, and sometimes, the file created without anything there....?
【Solved——Now acording to the suggestions, here's the answer】
1) Notice that I should remove "Cancellation" and mock an exception here:
static void Main(string[] args)
{
CancellationTokenSource cTokenSource = new CancellationTokenSource();
Task.Run(() =>
{
for (int i = 1; i < 6; i++)
{
if (i==5)
{
throw new Exception("Error occured!");
}
DoPrint(i, cTokenSource.Token);
}
},cTokenSource.Token)
.ContinueWith
(
t =>
{
Console.WriteLine("Error has happened now.");
Console.WriteLine(t.IsFaulted);
},
TaskContinuationOptions.OnlyOnFaulted
);
Thread.Sleep(400);
//cTokenSource.Cancel();
//Thread.Sleep(2000);
GC.Collect();
GC.WaitForPendingFinalizers();
//Thread.Sleep(6000);
Console.WriteLine("OK");
Console.ReadLine();
}
2) Then flatten the Exception (because's that an aggregative exception):
private static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
foreach (var item in e.Exception.Flatten().InnerExceptions)
{
Console.WriteLine(item.StackTrace);
}
e.SetObserved();
}
If OperationCanceledException is thrown for particular token, and this is the same token you passed when creating the task - it is not treated as unhandled\unobserved exception, because it's just normal, expected cancellation flow. This exception will instead just set task state to Cancelled. That is so in your case too:
var task = Task.Run(() =>
{
for (int i = 1; i < 6; i++)
{
// this exception is associated with cTokenSource.Token
cTokenSource.Token.ThrowIfCancellationRequested();
DoPrint(i, cTokenSource.Token);
}
}, cTokenSource.Token); // and this is the same token you pass when creating a task
If that were not the case (for example, you pass different token when creating a task) - exception will be intercepted by UnobservedTaskException handler.
Question is: why at all you want this exception to be treated as unobserved? You expected the task can be cancelled, you then cancel it, it's now in Cancelled state. Nothing unobserved\unhandled.

Task that ReadsKey from keyboard doesnt work - Consumer/Producer Pattern

I am implementing a single Producer/Consumer Pattern using BlockingCollection.
When i click 'c' from keyboard i want to cancel the operation using CancellationToken.
The strange thing is that if i press 'c' as fast as i can after i run the program, the program listen to the event.
If i click 'c' later lets say at 45000th iteration the program doesnt react.
I have a for loop that populates the producer.
for (int i = 0; i < 50000; i++)
{
logger.AddToQueue("Number with flush " + i, true);
}
logger.DataItems.CompleteAdding();
At the constructor of logger i call this method:
private Task t;
public void KeyPress()
{
t = Task.Run(() =>
{
if (Console.ReadKey(true).KeyChar == 'c')
{
cts.Cancel();
}
});
}
I dont know if the error is relevant to the other methods but i will post them just in case:
The addToQueue (Producer):
public void AddToQueue(String text, bool isFlushOn) {
Consumer(isFlushOn);
try {
_dataItems.TryAdd(new LogLine() { Text = text, Timestamp = DateTime.Now }, 0, ct);
} catch (OperationCanceledException) {
_dataItems.CompleteAdding();
}
}
and the consumer:
Task task = null;
public void Consumer(bool isStopWithFlushOn)
{
if (task == null)
{
task = Task.Run(() =>
{
while (!_dataItems.IsCompleted) {
try {
LogLine data = null;
if (!_dataItems.TryTake(out data, 5, ct)) {
Console.WriteLine(" Take Blocked");
} else {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(data.Timestamp.ToString("yyyy-MM-dd HH:mm:ss:fff"));
stringBuilder.Append("\t");
stringBuilder.Append(data.LineText());
stringBuilder.Append("\t");
_writer.WriteLine(stringBuilder.ToString());
Console.WriteLine(" Take:{0}", data.Text);
}
} catch (OperationCanceledException) {
if (isStopWithFlushOn) {
Console.WriteLine("Canceled with flush.");
foreach (var dataItem in _dataItems.GetConsumingEnumerable()) {
Console.WriteLine("Canceled Take:{0}", dataItem.Text);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(dataItem.Timestamp.ToString("yyyy-MM-dd HH:mm:ss:fff"));
stringBuilder.Append("\t");
stringBuilder.Append("Number with flush " + dataItem.LineText());
stringBuilder.Append("\t");
_writer.WriteLine(stringBuilder.ToString());
Thread.SpinWait(500000);
}
} else {
Console.WriteLine("Canceled without flush.");
break;
}
}
}
Console.WriteLine("\r\nNo more items to take.");
});
}
}

How to cancel the thread after timeout

I have a multi-threaded application and i'm using this to control the no.of processes (2). I want to process files only for specified time duration. Below is my approach. I'm getting The CancellationTokenSource has been disposed. error.
If i'm not dispoing the cts.Dispose(); then the process is not stooping after 10 sec. It is keep on processing till 1000. Can any one help me here.
Note: I've a 1000 files. Requirement is process files with in a given time (10 sec) by controlling the number of process (2) and sleep in between (some x ms).
Below is my code
class Program
{
static void Main(string[] args)
{
try
{
LimitedConcurrencyLevelTaskScheduler lcts = new LimitedConcurrencyLevelTaskScheduler(2);
List<Task> tasks = new List<Task>();
TaskFactory factory = new TaskFactory(lcts);
CancellationTokenSource cts = new CancellationTokenSource();
for (int i = 0; i < 1000; i++)
{
int i1 = i;
var t = factory.StartNew(() =>
{
if (cts != null)
Console.WriteLine("{0} --- {1}", i1, GetGuid(cts.Token));
}, cts.Token);
tasks.Add(t);
}
Task.WaitAll(tasks.ToArray(), 10000, cts.Token);
cts.Dispose();
Console.WriteLine("\n\nSuccessful completion.");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private static Guid GetGuid(CancellationToken cancelToken)
{
if (cancelToken.IsCancellationRequested)
{
return Guid.Empty;
}
Thread.Sleep(TimeSpan.FromSeconds(1));
return Guid.NewGuid();
}
}
What you can do is you can run a Task that will change your Cancellation Token state to canceled after some time.
Like this :
class Program
{
public static void ProcessFiles(CancellationToken cts)
{
try
{
LimitedConcurrencyLevelTaskScheduler lcts = new LimitedConcurrencyLevelTaskScheduler(2);
List<Task> tasks = new List<Task>();
TaskFactory factory = new TaskFactory(lcts);
for (int i = 0; i < 1000; i++)
{
int i1 = i;
var t = factory.StartNew(() =>
{
if (cts != null) Console.WriteLine("{0} --- {1}", i1, GetGuid());
}, cts);
tasks.Add(t);
}
Task.WaitAll(tasks.ToArray());
Console.WriteLine("\n\nSuccessful completion.");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
static void Main(string[] args)
{
CancellationTokenSource cts = new CancellationTokenSource();
Task.Factory.StartNew(() => { Thread.Sleep(10000); cts.Cancel(); });
ProcessFiles(cts.Token);
Console.ReadKey();
}
private static Guid GetGuid()
{
Thread.Sleep(TimeSpan.FromSeconds(1));
return Guid.NewGuid();
}
}

Categories

Resources