I have a Parallel.For loop which I use to peform a lot of HTTP request at a certain point when a scheduled task occurs like this:
Parallel.For(0, doc.GetElementsByTagName("ItemID").Count, i => {
var xmlResponse = PerformHttpRequestMethod();
});
Is there any way for me to set the loop to pause after the counter value hits 2,4,6,8,10 and so on...
so every 2 method calls it performs, sleep for 2 minutes lets say..
Is there any way I could achieve this ?
I recommend you to use Task.Delay.
Now your method is asyncronous using async/await.
public async Task DoSomething()
{
int i = 0;
while (i < doc.GetElementsByTagName("ItemID").Count)
{
Task.Run(() => PerformHttpRequestMethod());
if(i%2==0){
await Task.Delay(TimeSpan.FromMinutes(2));
//or simply:
await Task.Delay(120000);//120000 represents 2 minutes.
}
i++;
}
}
OR simply if you want to use for loop.
public async Task DoSomething()
{
for (int i = 0; i < doc.GetElementsByTagName("ItemID").Count; i++)
{
Task.Run(() => PerformHttpRequestMethod());
if(i%2==0){
await Task.Delay(TimeSpan.FromMinutes(2));
}
}
}
How would this 2nd example look if I'd want to do iterations from 0 to 4 then sleep 5 to 9 and so on... ?
public async Task DoSomething()
{
for (int i = 0; i < doc.GetElementsByTagName("ItemID").Count; i=i+5)
{
if( i%10 == 0 ){
for( int j=i;j<=i+4;j++){
Task.Run(() => PerformHttpRequestMethod());
}
}
else{
for(int j=i;j<=i+4;j++){
await Task.Delay(TimeSpan.FromMinutes(2));
}
}
}
}
Let's test the correctitude of algorithm.
i=0 -> (0%10==0 ->true) ,then will execute Task.Run(() => PerformHttpRequestMethod()) for i=(0,4)
i=5 -> (5%10==0 ->false), then will execute await Task.Delay(TimeSpan.FromMinutes(2)); for i=(5,9).
And so on...
I don't really see the point of using a Parallel.For if you want to sleep for x number of minutes or seconds every other iteration...how about using a plain old for loop?:
for(int i = 0; i < doc.GetElementsByTagName("ItemID").Count; ++i)
{
var xmlResponse = PerformHttpRequestMethod();
if (i % 2 == 0)
{
System.Threading.Thread.Sleep(TimeSpan.FromMinutes(2));
}
}
Or maybe you want to keep track of the how many iterations that are currently in flight?:
int inFlight = 0;
Parallel.For(0, doc.GetElementsByTagName("ItemID").Count, i => {
System.Threading.Interlocked.Increment(ref inFlight);
if (inFlight % 2 == 0)
System.Threading.Thread.Sleep(TimeSpan.FromMinutes(2));
var xmlResponse = PerformHttpRequestMethod();
System.Threading.Interlocked.Decrement(ref inFlight);
});
You can do that by combining a Parallel.For and a normal for loop:
for(var i = 0;i<doc.GetElementsByTagName("ItemID").Count;i = i+2)
{
Parallel.For(0, 2, i => {
var xmlResponse = PerformHttpRequestMethod();
});
Thread.Sleep(2000);
}
Related
I have a loop that creates 5 Tasks. How can I insert a Delay of 5 seconds between each Task. I don't know how to fit Task.Delay(5000) in there.
var tasks = new List<Task<int>>();
for (var i = 0; i < 5; i++)
{
tasks.Add(ProcessQueueAsync());
}
await Task.WhenAll(tasks);
My ProcessQueAsync method calls a server, retrieves data and returns and int.
private async Task<int> ProcessQueAsync()
{
var result = await CallToServer();
return result.Count;
}
for (var i = 0; i < 5; i++)
{
tasks.Add(ProcessQueueAsync());
await Task.Delay(5000);
}
Or:
for (var i = 0; i < 5; i++)
{
await ProcessQueueAsync();
await Task.Delay(5000);
}
Depending on that you want.
If you want the tasks to run one after the other, with a 5 second delay, you should perhaps look at Task.ContinueWith instead of using Task.WhenAll. This would allow you to run tasks in serial rather than in parallel.
So how can I run multiple tasks at once using a txt file as input.
Load Source Data
var lines = File.ReadAllLines("file.txt")
Run Tasks
forearch(var line in lines)
{
//I want to execute 3 tasks and each task needs to receive a line. At the end of each task he should pick up another line that has not been used and continue to the end of the file.
}
Have you looked at Parallel.ForEach?
use like :
Parallel.ForEach(File.ReadLines("file.txt"), new ParallelOptions { MaxDegreeOfParallelism = 3 }, line => { \\ do stuff })
Maybe something like this:
async void Main()
{
var lines = File.ReadAllLines("file.txt");
int i = 0;
var concurrency = 3;
while (i < lines.Length)
{
var tasks = new List<Task>(concurrency);
for (int j = 0; j < concurrency && i < lines.Length; j++)
{
tasks.Add(MyMethod(lines[i++]));
}
await Task.WhenAll(tasks);
}
}
public Task MyMethod(string s)
{
return Task.CompletedTask;
}
you can try this:
private static async Task Main(string[] args) {
const ushort concurrentWorkers = 5;
var lines = File.ReadAllLines("file.txt");
var concurrentSourceQueue = new ConcurrentQueue<string>(lines);
var worker = Enumerable.Range(0, concurrentWorkers)
.Select(_ => DoWorkAsync(concurrentSourceQueue));
await Task.WhenAll(worker);
}
private static async Task DoWorkAsync(ConcurrentQueue<string> queue) {
while (queue.TryDequeue(out var item)) {
//process line here
}
}
I'm newbie to use threading logic.
I declared ThreadPool.SetMaxThreads(10, 10) and create multiple thread same number of 10.
First request working well, I requested 2 more each different browser. following request fallen hang until finish first request's thread work.
Does ThreadPool.SetMaxThreads affected entire IIS application pool?
public ActionResult Index()
{
ThreadPool.SetMaxThreads(10, 10);
for (int i = 0; i < 10; i++)
{
Task.Factory.StartNew(() =>
{
try
{
Thread.Sleep(30000);
}
finally
{
}
});
}
return View();
}
Here's new code using semaphoreslim.
My Actual goal is only specified count of threads run at once.
for example I will download 9 files and assign each thread 1 download job, max 3 threads work.
public ActionResult Index()
{
int maxConcurrency = 3;
using (SemaphoreSlim concurrencySemaphore = new SemaphoreSlim(maxConcurrency))
{
List<Task> tasks = new List<Task>();
for (int i = 0; i < 9; i++)
{
concurrencySemaphore.Wait();
var t = Task.Factory.StartNew(() =>
{
try
{
// Here to actual my job logic.
Thread.Sleep(10000);
}
finally
{
concurrencySemaphore.Release();
}
});
tasks.Add(t);
}
Task.WaitAll(tasks.ToArray());
}
return View();
}
I'm working on a WPF-MVVM project and I need to implement asynchronous infinite loops in some background threads. What I have done in the ViewModel is
public TestVM()
{
LineIO_Task();
//some other work
}
and LineIO_Task is defined as
public void LineIO_Task()
{
for (int i = 0; i < 7; i++)
{
Task GetP = new Task(() => { EnPost(Lines[i]); }, TaskCreationOptions.LongRunning);
GetP.Start();
}
}
Lines is an ObservableCollection that is initialized in TestVm.
And EnPost is defined as
public async void EnPost(Line l)
{
int last = 0;
while (true)
{
// do the work in the loop
int pno = l.Com.ReadPostNo();//read a serial port
if (pno != 0 && pno != last)
{
log.WriteLog(pno + " to " + l.ToString());
Dispatcher.Invoke(() =>
{
// update the UI
l.Posts.First(x => x.IsValid).Num = pno;
l.Posts.First(x => x.IsValid).IsValid = false;
LocalDb.InsertPost(l.Num, AssignedPost.ToList().Find(x => x.Num == pno));
});
pno = last;
}
await Task.Delay(500);
}
}
I've tried Task.Run(() => Method()), Task.Factory.StartNew(() => Method()),,async Task EnPost() and using a System.Timers.Timer. But no matter which way I use, the EnPost method just doesn't run. I put break-points in the method. It doesn't hit there. Am I using Task wrong?
I'm guessing this is a "captured variable" issue; try:
for (int i = 0; i < 7; i++)
{
int index = i;
Task GetP = new Task(() => { EnPost(Lines[index]); }, TaskCreationOptions.LongRunning);
GetP.Start();
}
(fixed by question edit) Note however that using the thread-pool for a very long lived task is not a good idea. You might want to use a full thread instead. Also; your TaskDelay may want to be inside the while loop, in which case you can ignore the previous comment, as it is no longer actually a very long lived single piece.
Thanks for #Marc and #Brian's answer. They mention the"captured variable" issue, so I tried
foreach (Line l in Lines)
{ ... }
It works finally.
I am newbie to parallel programming. I write the basic code below but it doesnt run always as I excepted.
Console.WriteLine ("Start");
Task task = Task.Factory.StartNew(() => {
for (int i = 0; i < 5; i++)
{
Console.WriteLine (i);
}
});
Console.WriteLine ("End");
I usually could not get the result of the loop 8-9 out of 10 trials. Sometimes it prints the loop results, sometimes not. But I it always prints the Start and End. Whats happening at the behind side ? Why sometimes I could not get the result of loop from time to time ?
Thanks in advance,
Your program is terminating before the parallel loop gets a chance to print any output.
Console.WriteLine ("Start");
Task task = Task.Factory.StartNew(() => {
for (int i = 0; i < 5; i++)
{
Console.WriteLine (i);
}
});
Console.ReadLine();
Console.WriteLine("End");
Pause by waiting for input, and you'll see the loop run correctly.
Add a readline at the end. You will see the following:
Start
End
0
1
2
3
4
Console.WriteLine("Start");
Task task = Task.Factory.StartNew(() =>
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
});
Console.WriteLine("End");
Console.ReadLine();
You must tell your main thread to wait till your task is over.
Your "End" was being printed in most cases before the task thread executed. Use TaskContinuationOptions to tell the parent thread to wait for its tasks threads to complete.
Console.WriteLine ("Start");
Task task = Task.Factory.StartNew(() => {
for (int i = 0; i < 5; i++)
{
Console.WriteLine (i);
}
});
task.ContinueWith(ant =>
{
Console.WriteLine("End");
}, TaskContinuationOptions.NotOnFaulted| TaskContinuationOptions.AttachedToParent);
task.Wait();