Run tasks in parallel and some of them consecutively - c#

I want to run method A and method B1 in parallel. This is working. But how can I run a method B2 after B1 has finished?
class Program
{
static void Main(string[] args)
{
//var firstTask = Task.Factory.StartNew(() => MethodB1());
//var secondTask = firstTask.ContinueWith( (antecedent) => MethodB2());
Action[] actionsArray =
{
() => MethodA(),
() => MethodB1(),
};
Parallel.Invoke(actionsArray);
}
private static void MethodA()
{
Console.WriteLine("A");
// more code is running here (30 min)
}
private static void MethodB1()
{
Console.WriteLine("B1");
// more code is running here (2 min)
}
private static void MethodB2()
{
Console.WriteLine("B2");
}
}
Edit:
I hope the following example will stop the confusion. ;)
A -> A -> A -> A -> A -> A -> A -> A -> A -> A -> A -> A -> A -> A
B1 -> B1 -> B1 -> B1 -> B1 -> B2 -> B2 -> B2

C# is a great language to do this and there are many ways to do it one is as the comment suggests another is this:
static void Main()
{
var t = MethodA();
MethodB1().ContinueWith((r) =>
MethodB2()).Wait();
t.Wait();
}
private static async Task MethodA()
{
await Task.Run(() =>
{
for (int i = 0; i < 40; i++)
{
Thread.Sleep(100);
Console.WriteLine("A");
}
});
}
private static async Task MethodB1()
{
await Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
Thread.Sleep(100);
Console.WriteLine("B1");
}
});
}
private static void MethodB2()
{
for (int i = 0; i < 10; i++)
{
Thread.Sleep(100);
Console.WriteLine("B2");
}
}

You can easily achieve this by using ContinueWith. Here is the code
public static void Main(string[] args)
{
var t1 = Task.Factory.StartNew(MethodA);
var t2 = Task.Factory.StartNew(MethodB1).ContinueWith(task => MethodB2());
Task.WaitAll(t1, t2); // If you want to wait here for finishing the above tasks
}
To depict the output you can try with the following implementation of MethodA, MethodB1 and MethodB2
private static void MethodA()
{
for (int i = 0; i < 100; i++)
{
Console.Write("A ");
Thread.Sleep(100);
}
}
private static void MethodB1()
{
for (int i = 0; i < 100; i++)
{
Console.Write("B1 ");
Thread.Sleep(100);
}
}
private static void MethodB2()
{
for (int i = 0; i < 100; i++)
{
Console.Write("B2 ");
Thread.Sleep(100);
}
}

This will not work with VS2017 and newer because async keyword is not supported on console app mains before VS2017. On older version, instead of await Task.WhenAll() you should do Task.WhenAll().Wait();
namespace ConsoleApp3
{
class Program
{
static async void Main(string[] args)
{
var taskA = Task.Run(() => MethodA()); //Start runnning taskA
var taskB1AndB2 = Task.Run(() => MethodB1()).ContinueWith(async (taskb1) => { await taskb1; await Task.Run(()=>MethodB2()); }).Unwrap(); //When taskB1 is complete, continue with taskB2
await Task.WhenAll(taskA, taskB1AndB2); //wait until all 3 tasks are completed
}
private static void MethodA()
{
Console.WriteLine("A");
// more code is running here (30 min)
}
private static void MethodB1()
{
Console.WriteLine("B1");
// more code is running here (2 min)
}
private static void MethodB2()
{
Console.WriteLine("B2");
}
}
}

One way is Delegate CallBack Mechanism class Program. The another can be event based Here is Used First approach . Given with time samples
This is exactly what you want
class Program
{
static System.Collections.Concurrent.ConcurrentQueue<Action> leftOvers = new System.Collections.Concurrent.ConcurrentQueue<Action>();
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
Task.WaitAll(MethodA(), MethodB1(MethodB2));
}
Action callBack = null;
while (leftOvers.TryDequeue(out callBack))
{
callBack();
}
Console.ReadLine();
}
private static void QueueMethods(Action method)
{
leftOvers.Enqueue(method);
}
private async static Task MethodA()
{
await Task.Run(() => Console.WriteLine("A at" + DateTime.Now.TimeOfDay ));
}
private async static Task MethodB1(Action callBack)
{
await Task.Run(() => Console.WriteLine("B1 at" + DateTime.Now.TimeOfDay));
leftOvers.Enqueue(callBack);
}
private static void MethodB2()
{
Console.WriteLine("B2 at" + DateTime.Now.TimeOfDay);
}
}

Just add B2 after Parallel.Invoke. Parallel.Invoke waits to finish before going to the next line. https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/how-to-use-parallel-invoke-to-execute-parallel-operations
public static void Main(string[] args)
{
Action[] actionsArray =
{
() => MethodA(),
() => MethodB1()
};
Parallel.Invoke(actionsArray);
MethodB2();
}
private static void MethodA()
{
Console.WriteLine("A");
Thread.Sleep(3000);
// more code is running here (30 min)
}
private static void MethodB1()
{
Console.WriteLine("B1");
Thread.Sleep(200);
// more code is running here (2 min)
}
private static void MethodB2()
{
Console.WriteLine("B2");
}

Related

Why my task work only once?

I want to print every 2 sec number but and in the end i get only 0 what i need to do to get this every 2 sec?
result:
0
1
.
.
49
private static void Main(string[] args) {
Send();
}
public static async Task Send() {
for (int i = 0; i < 50; i++) {
Console.WriteLine(i);
await Task.Delay(2000);
}
}
well, simply because your Main method won't wait for the send method to finish and you can't use the await keyword in order for that to happened since the compiler won't allow an async Main, in that case you could simple use a Task.Run
private static void Main(string[] args)
{
Task.Run(async () =>
{
await Send();
}).Wait();
}
public static async Task Send()
{
for (int i = 0; i < 50; i++)
{
Console.WriteLine(i);
await Task.Delay(2000);
}
}
What you are missing is a Console.ReadLine() call, to halt the console from exiting the program before your task gets executed. Tested the code below and it works.
private static void Main(string[] args)
{
Send();
Console.ReadLine();
}
public static async Task Send()
{
for (int i = 0; i < 50; i++)
{
Console.WriteLine(i);
await Task.Delay(2000);
}
}
Building on Josephs answer, but in a more general "How to do asynchronous console apps"-way
Using asynchronous code in console apps can be a bit tricky. I generally use a substitute MainAsync method that the original Main() calls and makes a blocking wait on.
Here comes an example of how it could be done:
class Program
{
static void Main(string[] args)
{
Task mainTask = MainAsync(args);
mainTask.Wait();
// Instead of writing more code here, use the MainAsync-method as your new Main()
}
static async Task MainAsync(string[] args)
{
await Send();
Console.ReadLine();
}
public static async Task Send()
{
for (int i = 0; i < 50; i++)
{
Console.WriteLine(i);
await Task.Delay(2000);
}
}
}

Replace code with timer as opposed to thread sleep

According to this Stack Overflow discussion,using Thread.Sleep() is almost always a bad idea. How would I refactor my code to use a timer instead. I tried to make a start by doing the following:
namespace Engine
{
internal class Program
{
public static DbConnect DbObject = new DbConnect();
System.Timers.Timer timer = new System.Timers.Timer();
// error here
timer.Interval = 2000;
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Enabled=false;
}
}
but kept getting a cannot resolve symbol error message.
namespace Engine
{
internal class Program
{
public static DbConnect DbObject = new DbConnect();
private static void Main()
{
SettingsComponent.LoadSettings();
while (true)
{
try
{
for (int x = 0; x < 4; x++)
{
GenerateRandomBooking();
}
Thread.Sleep(2000);
GenerateRandomBids();
AllocateBids();
Thread.Sleep(2000);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
}
}
If you are using .Net 4.5 or later, you can use await instead of a Timer.
For example:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Demo
{
public static class Program
{
private static void Main()
{
Console.WriteLine("Generating bids for 30 seconds...");
using (var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)))
{
var task = GenerateBids(cancellationTokenSource.Token);
// You can do other work here as required.
task.Wait();
}
Console.WriteLine("\nTask finished.");
}
private static async Task GenerateBids(CancellationToken cancel)
{
while (!cancel.IsCancellationRequested)
{
Console.WriteLine("");
try
{
for (int x = 0; x < 4; x++)
GenerateRandomBooking();
await Task.Delay(2000);
if (cancel.IsCancellationRequested)
return;
GenerateRandomBids();
AllocateBids();
await Task.Delay(2000);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
private static void AllocateBids()
{
Console.WriteLine("AllocateBids()");
}
private static void GenerateRandomBids()
{
Console.WriteLine("GenerateRandomBids()");
}
private static void GenerateRandomBooking()
{
Console.WriteLine("GenerateRandomBooking()");
}
}
}
you can convert your code this one without using Thread.Sleep()
private static void Main()
{
SettingsComponent.LoadSettings();
//while (true)
{
try
{
RaiseRandomBooking(null);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
static void RaiseRandomBooking(object state)
{
for (int x = 0; x < 4; x++)
{
GenerateRandomBooking();
}
System.Threading.Timer tmr = new System.Threading.Timer(RaiseRandomBids, null, 0, 2000);
}
static void RaiseRandomBids(object state)
{
GenerateRandomBids();
AllocateBids();
System.Threading.Timer tmr = new System.Threading.Timer(RaiseRandomBooking, null, 0, 2000);
}

ThreadAbortException with await

I'm facing a weird bug.
I have something like 100 long running tasks and I want to run 10 of them in the same time.
I found something very similar to my need here : http://msdn.microsoft.com/en-us/library/hh873173%28v=vs.110%29.aspx in the Throttling section.
Here the C# code after simplification :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
public class Program
{
static void Main(string[] args)
{
Test();
}
public static async void Test()
{
var range = Enumerable.Range(1, 100).ToList();
const int CONCURRENCY_LEVEL = 10;
int nextIndex = 0;
var matrixTasks = new List<Task>();
while (nextIndex < CONCURRENCY_LEVEL && nextIndex < range.Count())
{
int index = nextIndex;
matrixTasks.Add(Task.Factory.StartNew(() => ComputePieceOfMatrix()));
nextIndex++;
}
while (matrixTasks.Count > 0)
{
try
{
var imageTask = await Task.WhenAny(matrixTasks);
matrixTasks.Remove(imageTask);
}
catch (Exception e)
{
Console.Write(1);
throw;
}
if (nextIndex < range.Count())
{
int index = nextIndex;
matrixTasks.Add(Task.Factory.StartNew(() => ComputePieceOfMatrix()));
nextIndex++;
}
}
await Task.WhenAll(matrixTasks);
}
private static void ComputePieceOfMatrix()
{
try
{
for (int j = 0; j < 10000000000; j++) ;
}
catch (Exception e)
{
Console.Write(2);
throw;
}
}
}
}
When running it from a Unit Test a have a ThreadAbortException in ComputePieceOfMatrix.
Do you have any idea ?
Edit :
According to a comment, I tried this :
static void Main(string[] args)
{
Run();
}
private static async void Run()
{
await Test();
}
public static async Task Test()
{
var range = Enumerable.Range(1, 100).ToList();
But it's exactly the same.
1.Your code causes exception
try
{
for (int j = 0; j < 10000000000; j++) ;
}
catch (Exception e)
{
Console.Write(2);
throw;
}
Just a simple OverflowException becase 10000000000 - is long and j counter int.
2.Your main tread is exiting before child threads run to finish. Most likely you are getting ThreadAbortException because Threads are closed by runtime
3.await Test() - correctly just call Test(), and await Task.WhenAny without await as well
Change the return type of Test() to Task, then wait for that Task to finish before your program reaches the end.
static void Main(string[] args)
{
Test().Wait();
}
public static async Task Test()
{
// ...
}
I would change your Test from a void to a Task return type and in the main method I would do in place of Test();
Task t = Test();
t.Wait();

Waiting for a 3rd party thread to finish

I need to call a 3rd party code that optionally starts a new thread, performs some processing, and then calls a different method on my object. What I need is wait for the 3rd party processing to be finished, then return from the original method. In other words, I have a class like this (C#):
class MyClass: IThirdPartyInterface {
void MyMethod() {
//some preprocessing
//call a 3rd party static method
ThirdParty.DoSomething(this);
}
void FinishedProcessing() {
//some postprocessing
//???
}
}
I want to modify MyMethod so that it return only after the thread that started in DoSomething has finished its execution and called the FinishedProcessing method. Since the thread is started by the third party code, I don't have access to it, so I cannot use Thread.Join here. So, what do I do instead?
You need to use an System.Threading.AutoResetEvent, it would be like this:
class MyClass: IThirdPartyInterface {
AutoResetEvent _event = new AutoResetEvent(false);
void MyMethod() {
ThirdParty.DoSomething(this);
_event.WaitOne();
}
void FinishedProcessing() {
_event.Set();
}
}
If the thread continues running after your FinishedProcessing method is called by the 3rdparty class, it would be a little diferent:
class MyClass: IThirdPartyInterface {
AutoResetEvent _event = new AutoResetEvent(false);
Thread _thread;
void MyMethod() {
ThirdParty.DoSomething(this);
_event.WaitOne();
_thread.Join();
}
void FinishedProcessing() {
_thread = Thread.CurrentThread;
_event.Set();
}
}
Make your MyMethod() async and then run thirdparty method inside your custom await method, moething like this:
private async void MyMethod()
{
var result = await WaitAsynchronouslyAsync();
}
public async Task<string> WaitAsynchronouslyAsync()
{
await ThirdParty.DoSomething(this);
return "Finished";
}
If ThirdParty.DoSomething does not support async pattern
you can use additional proxy with finalizer.
But it could affect application performance like a "while(myBoolFlag){}".
class Program
{
static void Main(string[] args)
{
var list = new List<ManualResetEvent>();
for (var i = 0; i < 10000; i++)
{
var m = new ManualResetEvent(false);
list.Add(m);
new Thread(Start).Start(m);
if (i > 0 && (i % 10) == 0)
for (int j = i - 10; j < i; j++)
{
list[j].WaitOne(1000);// wait signal
GC.Collect(); //force finalizer
A.Print();
}
}
}
private static void Start(object obj)
{
new A(obj as ManualResetEvent, null);
}
}
public class A : IThirdPartyInterface
{
public static long time1;
public static long count1;
private DateTime start = DateTime.Now;
private ManualResetEvent _stop;
private IThirdPartyInterface _origin;
public A(ManualResetEvent stop, IThirdPartyInterface origin)
{
_stop = stop;
_origin = origin;
}
~A()
{
Interlocked.Increment(ref count1);
Interlocked.Add(ref time1, (long)(DateTime.Now - start).TotalMilliseconds);
_stop.Set(); //send signal
}
public static void Print()
{
Console.Write("\r" + A.time1 + "\\" + A.count1 + " ");
if (A.count1 != 0)
Console.Write((A.time1 / A.count1).ToString());
}
}

Wait issue in multithreading

class MultiThreading
{
public class ThreadClass
{
public string InputString { get; private set; }
public int StartPos { get; private set; }
public List<SearchAlgorithm.CandidateStr> completeModels;
public List<SearchAlgorithm.CandidateStr> partialModels;
public ThreadClass(string s, int sPos)
{
InputString = s;
StartPos = sPos;
completeModels = new List<SearchAlgorithm.CandidateStr>();
partialModels = new List<SearchAlgorithm.CandidateStr>();
}
public void Run(int strandID)
{
Thread t = new Thread(() => this._run(strandID));
t.Start();
}
private void _run(int strandID)
{
SearchAlgorithm.SearchInOneDirection(strandID, ref this.completeModels, ref this.partialModels);
}
public static void CombineResult(
List<ThreadClass> tc,
out List<SearchAlgorithm.CandidateStr> combinedCompleteModels,
out List<SearchAlgorithm.CandidateStr> combinedPartialModels)
{
// combine the result
}
}
}
class Program
{
static void Main(string s, int strandID)
{
int lenCutoff = 10000;
if (s.Length > lenCutoff)
{
var threads = new List<MultiThreading.ThreadClass>();
for (int i = 0; i <= s.Length; i += lenCutoff)
{
threads.Add(new MultiThreading.ThreadClass(s.Substring(i, lenCutoff), i));
threads[threads.Count - 1].Run(strandID);
}
**// How can I wait till all thread in threads list to finish?**
}
}
}
My question is how can I wait till all threads in "threads" list to finish and then do the call CombineResult method?
Thanks
You can add a List<Thread> structure to keep record of all your threads
private List<Thread> threads = new List<Thread>();
Then populate the list with the threads
public void Run(int strandID)
{
Thread t = new Thread(() => this._run(strandID));
t.Start();
threads.Add(t);
}
Lastly, you can have a method that calls Join for each thread in a list. It is usually a good practise to have a timeout delay so your program will not block forever (in case there is a bug in a thread)
public void WaitAll(List<Thread> threads, int maxWaitingTime)
{
foreach (var thread in threads)
{
thread.Join(maxWaitingTime); //throws after timeout expires
}
}
An alternative would be to use a Task class and to call Task.WaitAll
Have ThreadClass expose a means to join the thread:
private Thread nativeThread;
public void Run(int strandID)
{
nativeThread = new Thread(() => this._run(strandID));
nativeThread.Start();
}
public void Join()
{
nativeThread.Join();
}
And then use ThreadClass.Join on each thread after you start them:
var threads = new List<ThreadClass>();
for (int i = 0; i <= s.Length; i += lenCutoff)
{
threads.Add(new ThreadClass(s.Substring(i, lenCutoff), i));
threads[threads.Count - 1].Run(strandID);
}
// Waits for each thread to finish in succession
threads.ForEach(t => t.Join());
Or, throw away your ThreadClass and enjoy System.Threading.Tasks:
// e.g. class Models { Complete; Partial; }
// private Models Search(string source, int offset, int length, int ID)
var tasks = new List<Task<Models>>(
from x in Enumerable.Range(0, s.Length / lenCutoff)
select Task.Factory.StartNew<Models>(
() => Search(s, x, lenCutoff, strandID));
);
// private Models CombineResults(IEnumerable<Models> results)
var combine = Task.Factory.ContinueWhenAll<Models>(
tasks.ToArray(),
ts => CombineResults(ts.Select(t => t.Result)));
combine.Wait();
Models combinedModels = combine.Result;
Well I see the answer has already been chosen, but I had already started on writing a solution using System.Threading.Tasks as proposed by several others. Rather than using LINQ, I have tried to match the structure of the original code as much as possible:
class SearchClass
{
public String InputString { get; private set; }
public int StartPos { get; private set; }
public List<string> completeModels;
public List<string> partialModels;
public SearchClass(string s, int sPos)
{
InputString = s;
StartPos = sPos;
completeModels = new List<string>();
partialModels = new List<string>();
}
public void Run(int strandID)
{
// SearchAlgorithm.SearchInOneDirection(...);
}
// public static void CombineResult(...){ };
}
class Program
{
static void Main(string s, int strandID)
{
int lenCutoff = 10000;
if (s.Length > lenCutoff)
{
var searches = new List<SearchClass>();
var tasks = new List<System.Threading.Tasks.Task>();
for (int i = 0; i < s.Length; i += lenCutoff)
{
SearchClass newSearch = new SearchClass(s.Substring(i, lenCutoff), i);
searches.Add(newSearch);
tasks.Add(System.Threading.Tasks.Task.Factory.StartNew(()=>newSearch.Run(strandID)));
}
System.Threading.Tasks.Task.WaitAll(tasks.ToArray());
// Combine the result
}
}
}

Categories