Executing 2 methods parallel using C# - c#

I have a scenario to monitor the state of the ui test. If the test is running more than 30 mins, stop the test run and start with another test. Here is the code developed to simulate the same. I apologies if i am duplicating here.
Reference: execute mutiple object methods parallel
Here is the sample program that, developed in line with my requirement.I request experts to comment on my approach and suggest me the best of it.
<code>
namespace ParallelTasksExample
{
internal class Program
{
private static Stopwatch testMonitor;
private static int timeElapsed;
private static void Main(string[] args)
{
Parallel.Invoke(() => PrintNumber(), () => MonitorSequence());
}
private static void PrintNumber()
{
testMonitor = new Stopwatch();
testMonitor.Start();
for (int i = 0; i <= 10; i++)
{
System.Threading.Thread.Sleep(5000);
timeElapsed = testMonitor.Elapsed.Seconds;
Console.WriteLine("Running since :" + timeElapsed + " seconds");
}
}
private static void MonitorSequence()
{
while (timeElapsed < 25)
{
System.Threading.Thread.Sleep(2000);
Console.WriteLine("Time Elapsed :" + timeElapsed + " seconds");
}
testMonitor.Stop();
testMonitor.Reset();
Console.WriteLine("Test has taken more then 25 seconds. Closing the current test sequence initiated.");
}
}
}
</code>
I am facing an issue, when the actual code developed based on the above example.
task 1 is completed and task 2 is in progress. Meanwhile task 1 is waiting for task2 to finish. How can we make both tasks are independent?

Related

Deadlock using async Task and SemaphoreSlim

we are running an ASP.NET 6 webapplication and are having strange issues with deadlocks.
The app suddenly freezes after some weeks of operations and it seems that it might be caused by our locking mechanism with the SemaphoreSlim class.
I tried to reproduce the issue with a simple test-project and found something strange.
The following code is simply starting 1000 tasks where each is doing some work (requesting semaphore-handle, waiting for 10 ms and releasing the semaphore).
I expected this code to simply execute one task after another. But it freezes because of a deadlock in the first call of the DoWork method (at await Task.Delay(10)).
Does anyone know why this causes a deadlock? I tried exactly the same code with ThreadPool.QueueUserWorkItem instead of Task.Run and Thread.Sleep instead of Task.Delay and this worked as expected. But as soon as I use the tasks it stops working.
Here is the complete code-snippet:
internal class Program
{
static int timeoutSec = 60;
static SemaphoreSlim semaphore = new SemaphoreSlim(1);
static int numPerIteration = 1000;
static int iteration = 0;
static int doneCounter = numPerIteration;
static int successCount = 0;
static int failedCount = 0;
static Stopwatch sw = new Stopwatch();
static Random rnd = new Random();
static void Main(string[] args)
{
Task.WaitAll(TestUsingTasks());
}
static async Task TestUsingTasks()
{
while (true)
{
var tasks = new List<Task>();
if (doneCounter >= numPerIteration)
{
doneCounter = 0;
if (iteration >= 1)
{
Log($"+++++ FINISHED TASK ITERATION {iteration} - SUCCESS: {successCount} - FAILURES: {failedCount} - Seconds: {sw.Elapsed.TotalSeconds:F1}", ConsoleColor.Magenta);
}
iteration++;
sw.Restart();
for (int i = 0; i < numPerIteration; i++)
{
// Start indepdent tasks to do some work
Task.Run(async () =>
{
if (await DoWork())
{
successCount++;
}
else
{
failedCount++;
}
doneCounter++;
});
}
}
await Task.Delay(10);
}
}
static async Task<bool> DoWork()
{
if (semaphore.Wait(timeoutSec * 1000)) // Request the semaphore to ensure that one 1 task at a time can enter
{
Log($"Got handle for {iteration} within {sw.Elapsed.TotalSeconds:F1}", ConsoleColor.Green);
var totalSec = sw.Elapsed.TotalSeconds;
await Task.Delay(10); // Wait for 10ms to simulate some work => Deadlock seems to happen here
Log($"RELEASING LOCK handle for {iteration} within {sw.Elapsed.TotalSeconds:F1}. WAIT took " + (sw.Elapsed.TotalSeconds - totalSec) + " seconds", ConsoleColor.Gray);
semaphore.Release();
return true;
}
else
{
Log($"ERROR: TASK handle failed for {iteration} within {sw.Elapsed.TotalSeconds:F1} sec", ConsoleColor.Red);
return false;
}
}
static void Log(string message, ConsoleColor color)
{
Console.ForegroundColor = color;
Console.WriteLine(message);
Console.ForegroundColor = ConsoleColor.White;
}
}
Thanks in advance!
But it freezes because of a deadlock in the first call of the DoWork method (at await Task.Delay(10)).
I would argue that it is not deadlock but a thread starvation issue. If you wait long enough you will see that threads will be able to finish the simulation wait from time to time.
The quick fix here is using non-blocking WaitAsync call with await:
static async Task<bool> DoWork()
{
if (await semaphore.WaitAsync(timeoutSec * 1000))
{
...
}
}
Also note:
It is recommended to wrap the code after Wait.. into try-finally block and release the semaphore in the finally.
Incrementing counters in parallel environments better should be done in atomic fashion, for example with Interlocked.Increment.

how to run a timer in a finite loop in C#

I have a task where I have to record a video in multiple segments. Let's take the scenario in this way, the user has started recording a video through a webcam and after 5 seconds it has stopped the recording, now we have the value of 5 seconds and our system will start recording the video again for the next 5 seconds and save it in a file. This process will run for multiple times(the value is already set by the user, let's say 3 times).
This is what I want to do in real.
And the Block of code that I shared is an illustration of the real task where code will run a task wait for some time, and repeat the process till it meets a condition which in our case is 3.
This piece of code is working fine but sometimes it skips the counting of seconds. By skipping I mean it will show 1 then lag for 2 seconds then will show 2 and 3 and so on.
I am afraid if I use this technique it might give me the wrong output and I need to be very precise with the recording time.
Is there any way to improve this piece of code?
Stopwatch sw;
private void btnStart_Click(object sender, EventArgs e)
{
sw = new Stopwatch();
timer1.Enabled = true;
sw.Start();
}
int counter = 1;
private void timer1_Tick(object sender, EventArgs e)
{
if (sw.Elapsed > TimeSpan.FromSeconds(4))
{
sw.Reset();
if (counter < 3)
{
sw.Start();
counter++;
}
else
{
sw.Reset();
timer1.Stop();
counter = 0;
MessageBox.Show("Counter has finished +"counter.ToString());
}
}
lblTime.Text = string.Format("{0:hh\\:mm\\:ss}", sw.Elapsed);
}
The question is a bit unclear and doesn't explain what needs to run. That matters.
One way to repeat a 5-second task 3 times would be to use a CancellationTokenSource that triggers after 5 seconds inside a loop. The worker code would have to check a CancellationToken to see when it needs to terminate :
async Task DoWorkAsync(CancellationToken token)
{
while(!token.IsCancellationRequested)
{
// The Block
}
}
async void btnStart_Clicked(object sender,EventArgs args)
{
var count=3;
var sw = new Stopwatch();
for (int i=0;i<count;i++)
{
sw.Restart();
using var cts=new CancellationTokenSource(TimeSpan.FromSeconds(5));
await DoWorkAsync(cts.Token);
lblTime.Text = $("{sw.Elapsed:hh\\:mm\\:ss}");
}
MessageBox.Show($"Counter has finished + {count}");
}
The UI can be updated after each await call, or through a Progress class. If the code block runs for a long time it can be made to run in the background with Task.Run that can be cancelled using the same token. If the block executes asynchronous operations, they could be cancelled as well :
async Task DoWorkAsync(CancellationToken token,IProgress<string> pg)
{
try
{
while(!token.IsCancellationRequested)
{
await Task.Run(()=>{
//Do Work 1
pg.Report("Done 1");
//Do Work 2
pg.Report("Done 2");
},token);
}
}
catch(OperationCanceledException)
{
pg.Report("Time's up!");
}
}
async void btnStart_Clicked(object sender,EventArgs args)
{
var pg=new Progress(DisplayProgress);
var count=3;
var sw = new Stopwatch();
for (int i=0;i<count;i++)
{
sw.Restart();
using var cts=new CancellationTokenSource(TimeSpan.FromSeconds(5));
await DoWorkAsync(cts.Token,pg);
lblTime.Text = $("{sw.Elapsed:hh\\:mm\\:ss}");
}
MessageBox.Show($"Counter has finished + {count}");
}
void DisplayProgress(string msg)
{
lblMessage.Text=msg;
}

Show program runtime every 3 seconds

I'm learning async in C# and want to show a program runtime every three seconds. I have two solutions, but neither works completely properly.
Solution 1
In the first solution, I have a loop where I call two methods. The first performs the calculation and the second shows the startup time, which is divisible by 3.
namespace Async
{
class Program
{
static void Main(string[] args)
{
PerformLoop();
Console.ReadLine();
}
public static async void PerformLoop()
{
Stopwatch timer = new Stopwatch();
timer.Start();
List<Task> l = new List<Task>();
for (int i = 0; i < 50; i++)
{
l.Add(AsyncCalculation(i));
l.Add(ShowTime(Convert.ToInt32(timer.Elapsed.TotalMilliseconds)));
}
await Task.WhenAll(l);
timer.Stop();
Console.WriteLine("Total execution time: " +
timer.Elapsed.TotalMilliseconds);
}
public async static Task AsyncCalculation(int i)
{
var result = 10 * i;
Console.WriteLine("Calculation result: " + result);
}
public async static Task ShowTime(int execTime)
{
if (execTime % 3 == 0)
{
Console.WriteLine("Execution time: " + execTime);
}
}
}
}
Solution 2
In the second solution, I call two methods in a loop. The first performs calculations and the second displays the operation time after 3 seconds. Unfortunately, in this case, the second method blocks the execution of the first.
namespace Async
{
class Program
{
static void Main(string[] args)
{
CallMethod();
Console.ReadLine();
}
public static async void CallMethod()
{
for (int i = 0; i < 50; i++)
{
var results = Calculation(i);
var calcResult = results.Item1;
var time = results.Item2;
ShowResult(calcResult);
await ShowDelayTime(time);
}
}
public static void ShowResult(int calcResult)
{
Console.WriteLine("Calculation result: " + calcResult);
}
public async static Task ShowDelayTime(int execTime)
{
await Task.Delay(3000);
Console.WriteLine("Execution time: " + execTime);
}
public static Tuple<int, int> Calculation(int i)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var result = 10 * i;
stopwatch.Stop();
return Tuple.Create(result,
Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds));
}
}
}
I have no idea how to continuously display the calculation results and show the running time of the program by three seconds :(((
Edit
Expected output (example):
Calculation result: 0
Calculation result: 10
Execution time: 3 seconds
Calculation result: 20
Calculation result: 30
Calculation result: 40
Execution time: 6 seconds
Calcultion result: 50
//Next iterations
The program now shows the result, waits three seconds, and then go to next iteration. I want iterations for calculations to show regardless (independently) of time. I want the time to show every three seconds of the program running.
You could use a System.Threading.Timer in order to invoke a callback every 3 seconds, and a Stopwatch in order to measure the elapsed seconds since the start of the program:
var stopwatch = Stopwatch.StartNew();
var timer = new System.Threading.Timer(_ =>
{
Console.WriteLine($"Execution time: {stopwatch.Elapsed.TotalSeconds:#,0} seconds");
}, null, 3000, 3000);

Await Task.Delay() spend too much time

In C# I have an example:
public async static Task TaskTest(int i)
{
await Task.Delay(1);
Console.WriteLine($"{i}. {DateTime.Now.ToString("HH:mm:ss fff")} " +
$"ThreadId:{Thread.CurrentThread.ManagedThreadId} Start");
int count = 1;
while (true)
{
DoSomeThing(count);
var stopWatch = new Stopwatch();
stopWatch.Start();
await Task.Delay(100);
stopWatch.Stop();
if (stopWatch.Elapsed.TotalMilliseconds > 200)
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"Id:{count} Time:{DateTime.Now.ToString("HH:mm:ss fff")} " +
$"ThreadID:{Thread.CurrentThread.ManagedThreadId} Time Delay:{stopWatch.Elapsed.TotalMilliseconds }");
Console.ForegroundColor = ConsoleColor.White;
count++;
}
}
public async static Task DoSomeThing(int index)
{
await Task.Delay(1);
Task.Delay(1000).Wait();
}
private static void Main(string[] args)
{
int i = 1;
while (i < 2)
{
TaskTest(i);
Task.Delay(1).Wait();
i++;
}
Console.ReadKey();
}
Here is my result
Result
Id:8 Time:23:03:59 972 ThreadID:12 Time Delay:582.6348
Id:22 Time:23:04:01 974 ThreadID:14 Time Delay:552.7234000000001
Id:42 Time:23:04:04 967 ThreadID:8 Time Delay:907.3214
I don't know why Task sometimes delay more than 200 milliseconds.
Update:
Thank for all answer.
I update my code to use Thread and Thread.Sleep() and Task.Run(). I increase number of Threads run forever to 500. I tested in 30 minutes and 500 threads never sleep more than 200ms.
Do you think that is bad code?
Please leave a comment!
Thank you so much!
public static void TaskTest(object i)
{
Console.WriteLine($"{i} Start");
int count = 1;
while (true)
{
// Open Task to do work
Task.Run(() => { DoSomeThing(count); });
var stopWatch = new Stopwatch();
stopWatch.Start();
Thread.Sleep(100);
stopWatch.Stop();
if (stopWatch.Elapsed.TotalMilliseconds > 200)
{
Console.WriteLine($"Id:{count} Time:{DateTime.Now.ToString("HH:mm:ss fff")} " +
$"ThreadID:{Thread.CurrentThread.ManagedThreadId} Time Delay:{stopWatch.Elapsed.TotalMilliseconds }");
}
count++;
}
}
public static void DoSomeThing(int index)
{
Thread.Sleep(1000); // Time spent complete work
}
private static void Main(string[] args)
{
int i = 0;
while (i < 500)
{
// Open Thread for TaskTest
Thread tesThread = new Thread(TaskTest);
tesThread.IsBackground = true;
tesThread.Start(i);
i++;
}
Console.WriteLine("Finish init");
Console.ReadKey();
}
Task.Delay, like any other multi-threaded sleep function, yields the thread it's running on back to the system (or in the case of the thread pool, back to the thread pool scheduler), asking to be re-scheduled some time after the amount of time specified.
That is the only guarantee you have, that it will wait at least the amount specified. How long it will actually wait heavily depends on your thread pool load (you're delaying an awful lot of tasks there), general system load (there's thousands of threads at any given point in time to be scheduled on an average computer OS) and on your CPU&OS's capability to schedule threads quickly (in Windows, look at timeBeginPeriod).
Long story short, if precise timing matters to you, don't relinquish your thread.

How to call a GPU task periodically using Hybridizer

I'm trying to use hybridizer for computations using a GPU in C#. I tried to embed my GPU code in a .NET library use Altimesh Hybridizer. Let's call it GPU_DLL.
This library has to be used in another project, let's call it Test_GPU_Caller. The GPU code is called periodically using a timer as shown in the following code :
class Program
{
static GPU_DLL.GPU_DLL gpuDllTest = new GPU_DLL.GPU_DLL();
static void Main(string[] args)
{
Timer tmr = new Timer(100);
tmr.Elapsed += Tmr_Elapsed;
tmr.Start();
while (true) ;
}
private static void Tmr_Elapsed(object sender, ElapsedEventArgs e)
{
gpuDllTest.Test("GPU_DLL_CUDA.dll");
}
}
Test function is implemented in a .NET library with the following code :
public class GPU_DLL
{
[EntryPoint("run")]
public void Run(int N, double[] a, double[] b)
{
Parallel.For(0, N, i => { a[i] += b[i]; });
}
public void Test(string dllName)
{
// 268 MB allocated on device -- should fit in every CUDA compatible GPU
int N = 1024 * 1024 * 16;
double[] acuda = new double[N];
double[] adotnet = new double[N];
double[] b = new double[N];
Random rand = new Random();
//Initialize acuda et adotnet and b by some doubles randoms, acuda and adotnet have same numbers.
for (int i = 0; i < N; ++i)
{
acuda[i] = rand.NextDouble();
adotnet[i] = acuda[i];
b[i] = rand.NextDouble();
}
cudaDeviceProp prop;
cuda.GetDeviceProperties(out prop, 0);
HybRunner runner = HybRunner.Cuda(dllName).SetDistrib(prop.multiProcessorCount * 16, 128);
// create a wrapper object to call GPU methods instead of C#
dynamic wrapped = runner.Wrap(this);
// run the method on GPU
wrapped.Run(N, acuda, b);
// run .Net method
Run(N, adotnet, b);
// verify the results
for (int k = 0; k < N; ++k)
{
if (acuda[k] != adotnet[k])
Console.Out.WriteLine("ERROR !");
}
Console.Out.WriteLine("DONE");
//Thread.Sleep(10000);
}
}
GPU_DLL has been Hybridized first, and compiled. When i launch the program, i get an error :
System.ArgumentException : 'Un élément avec la même clé a déjà été ajouté.' (in french...)
Does someone know how to use GPU code called periodically using Hybridizer ? A sample project is welcome ;)
Best regards,
Valentin
The problem you are facing seems to relate to timer calling the function a second time before first call has finished. According to documentation, your timer setup will call the timer function callback every 100 milliseconds, however it will not wait for previous run to be done (running it on my system requires 1.3 seconds for first iteration, and ~650ms on subsequent calls).
HybRunner is not thread-safe. Also, note that the CUDA context is attached to a thread, and using another thread requires another CUDA context.
Here is a alternate implementation to address your issue using a worker thread that executes GPU-related tasks:
First, declare synchronization components:
static bool workerrunning = false;
static object started = new object();
static Queue<object> tasks = new Queue<object>();
static object watch = new object();
The worker thread loop could be the following:
public static void HybridLoop(object p)
{
lock (started)
{
workerrunning = true;
Monitor.Pulse(started);
}
while (workerrunning)
{
object currenttask = null;
// get next task
lock (watch)
{
if (tasks.Count == 0)
{
Monitor.Wait(watch);
}
if (tasks.Count != 0)
{
currenttask = tasks.Dequeue();
// NOTE: here, we illustrate more tasks than doable => clear
tasks.Clear();
}
}
if (currenttask != null)
{
gpuDllTest.Test("GPU_DLL_CUDA.dll");
}
}
}
Here, we clear the task queue as it is populated faster than consumed.
The code to start the worker thread:
System.Threading.Thread hybridrunner = new System.Threading.Thread(HybridLoop);
lock(started)
{
hybridrunner.Start();
Monitor.Wait(started);
}
Once worker is started, timer can be started:
System.Timers.Timer tmr = new System.Timers.Timer(100);
tmr.Elapsed += Tmr_Elapsed;
tmr.Start();
Console.Out.WriteLine("Runner started - press return to stop");
var key = Console.Read();
Your timer elapse function is simply a task enqueing:
private static void Tmr_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
lock (watch)
{
tasks.Enqueue(1);
Monitor.Pulse(watch);
}
}
Once done, runner can be stopped to avoid tail-running thread:
workerrunning = false;
lock (watch)
{
tmr.Stop();
tasks.Enqueue(0);
Monitor.Pulse(watch);
}
Console.Out.WriteLine("Runner stopping");
hybridrunner.Join();
Console.Out.WriteLine("Runner stopped");
Example execution log:
DONE
Execution took 1026 milliseconds
DONE
Execution took 642 milliseconds
DONE
Execution took 614 milliseconds
Runner started - press return to stop
DONE
DONE
DONE
Runner stopping
DONE
Runner stopped
As a final note, you may want to do some initialization such as HybRunner.Cuda(), only once, and then perform other tasks in the same worker thread.

Categories

Resources