synchronize two thread category - c#

I am trying to develop an application where there are two thread category: A thread and the thread B.
if thread A is in the critical section, the thread B must wait until all thread A finish.
and if the thread B are in the critical section, the thread A must wait until all thread A complete
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplicationPontAVoieUnique
{
class Program
{
public static int nbrA=0;
public static int nbrB = 0;
public static Semaphore semA;
public static Semaphore semB;
public static Semaphore semNbrA;
public static Semaphore semNbrB;
static void Main(string[] args)
{
semNbrA = new Semaphore(1, 2);
semNbrB = new Semaphore(1, 2);
semA = new Semaphore(0, 3);
semB = new Semaphore(0, 3);
Thread A1 = new Thread(new ThreadStart(ActionThreadA));
A1.IsBackground = true;
A1.Name = "A1";
A1.Start();
Thread B1 = new Thread(new ThreadStart(ActionThreadB));
B1.IsBackground = true;
B1.Name = "B1";
B1.Start();
Thread A2 = new Thread(new ThreadStart(ActionThreadA));
A2.IsBackground = true;
A2.Name = "A2";
A2.Start();
Thread B2 = new Thread(new ThreadStart(ActionThreadB));
B2.IsBackground = true;
B2.Name = "B2";
B2.Start();
Thread A3 = new Thread(new ThreadStart(ActionThreadA));
A3.IsBackground = true;
A3.Name = "A3";
A3.Start();
Thread B3 = new Thread(new ThreadStart(ActionThreadB));
B3.IsBackground = true;
B3.Name = "B3";
B3.Start();
Thread A4 = new Thread(new ThreadStart(ActionThreadA));
A4.IsBackground = true;
A4.Name = "A4";
A4.Start();
Thread B4 = new Thread(new ThreadStart(ActionThreadB));
B4.IsBackground = true;
B4.Name = "B4";
B4.Start();
Console.ReadLine();
}
static void ActionThreadA()
{
semNbrA.WaitOne();
nbrA++;
if (nbrA == 1)
{
Console.WriteLine(Thread.CurrentThread.Name + " I'am the first A ");
semB.WaitOne();
}
semNbrA.Release();
Console.WriteLine(Thread.CurrentThread.Name + " I'am in the cs ");
Thread.Sleep(5000); //sc
semNbrA.WaitOne();
nbrA--;
if (nbrA == 0)
{
Console.WriteLine(Thread.CurrentThread.Name + " I'am the last A ");
semB.Release();
}
semNbrA.Release();
}
static void ActionThreadB()
{
semNbrB.WaitOne();
nbrB++;
if (nbrB == 1)
{
Console.WriteLine(Thread.CurrentThread.Name + " I'am the first B ");
semA.WaitOne();
}
semNbrB.Release();
Console.WriteLine(Thread.CurrentThread.Name + " I'am in the cs ");
Thread.Sleep(5000);
semNbrB.WaitOne();
nbrB--;
if (nbrB == 0)
{
Console.WriteLine(Thread.CurrentThread.Name + " I'am the last B ");
semA.Release();
}
semNbrB.Release();
}
}
}

What's the question?
You can use lock lock and AutoResetEvent instead of Semaphores.

Related

Semaphore - task to run faster with semaphore

My school task is to build a code with the same loop delay but using semaphore to run the task faster. This is for learning semaphore.
I have made the script as follows however the delay between two similar threads are 1.4 seconds. Is there a way by adjusting semaphore to make the program run faster.
using System;
using System.Threading;
using System.Diagnostics;
//Example in using sleep() and Threads in C#
namespace ThreadSys
{
class ThreadClass
{
int loopDelay, loopCnt;
Thread cThread;
static Semaphore _sem = new Semaphore(1, 5);
public ThreadClass(string name, int delay)
{
loopCnt = 0;
loopDelay = delay;
cThread = new Thread(new ThreadStart(this.run));
cThread.Name = name;
cThread.Start();
}
// The main function in the ThreadClass
void run()
{
do
{
_sem.WaitOne();
Console.Write(cThread.Name + ":" + DateTime.Now.ToString(" HH:mm:ss.fff "));
Console.Write(cThread.Name + ":" + " Hello ");
Console.Write(cThread.Name + ":" + " A number ");
Console.Write(cThread.Name + ":" + " Year ");
Console.WriteLine();
Thread.Sleep(loopDelay);
loopCnt++;
_sem.Release();
} while (loopCnt < 40);
Console.WriteLine(cThread.Name + "*Finished* ");
}
}
// The application
class ThreadSys
{
static void Main(string[] args)
{
ThreadClass dt1 = new ThreadClass("[T1]", 95);
ThreadClass dt2 = new ThreadClass("[T2]", 191);
ThreadClass dt3 = new ThreadClass("[T3]", 287);
ThreadClass dt4 = new ThreadClass("[T4]", 383);
ThreadClass dt5 = new ThreadClass("[T5]", 479);
}
}
}

Multithreads - passing arguments and receiving results

I am trying various options on working with threads. I wrote the code below, but it does not work as expected. How can I fix the code, so that the main function will correctly display the product?
using System;
using System.Threading;
namespace MultiThreads
{
class Program
{
static int prod;
public static void Main(string[] args)
{
Thread thread = new Thread(() => Multiply(2, 3));
thread.Start();
for(int i = 0; i < 10; i++) { // do some other work until thread completes
Console.Write(i + " ");
Thread.Sleep(100);
}
Console.WriteLine();
Console.WriteLine("Prod = " + prod); // I expect 6 and it shows 0
Console.ReadKey(true);
}
public static void Multiply(int a, int b)
{
Thread.Sleep(2000);
prod = a * b;
}
}
}
Ignoring the fact that you should be using non-blocking tasks, volatile properties and other coroutine principals, the immediate reason your program does not work as intended is because you didn't re-join the child thread back into the parent. See Join
Without the join, the Console.WriteLine("Prod = " + prod); occurs before the assignment prod = a * b;
static int prod;
static void Main(string[] args)
{
Thread thread = new Thread(() => Multiply(2, 3));
thread.Start();
for (int i = 0; i < 10; i++)
{ // do some other work until thread completes
Console.Write(i + " ");
Thread.Sleep(100);
}
thread.Join(); // Halt current thread until the other one finishes.
Console.WriteLine();
Console.WriteLine("Prod = " + prod); // I expect 6 and it shows 0
Console.ReadKey(true);
}
public static void Multiply(int a, int b)
{
Thread.Sleep(2000);
prod = a * b;
}

C# threading: loop counter is printing last value only

Why does this code:
private static void UdpPortListener(UInt16 Port)
{
Console.WriteLine("Listening to port: {0}", Port);
}
static void Main(string[] args)
{
List<Thread> ts = new List<Thread>();
for(int i = 0; i < 20; i++)
{
Thread t = new Thread(() =>
{
UdpPortListener(Convert.ToUInt16(52000 + i));
});
t.IsBackground = false;
ts.Add(t);
}
ts.ForEach((x) => x.Start());
}
produce this output:
Listening to port: 52020
Listening to port: 52020
...
Listening to port: 52020
When I was writing this code I hoped it would print incrementing numbers starting from 52000
Its the closure you've got there that closes over your for loop variable.
That i variable is promoted at compile time .. because its a loop counter and its actually accessed outside of the loop (in the thread delegate here):
Thread t = new Thread(() =>
{
UdpPortListener(Convert.ToUInt16(52000 + i));
}); // ^^^ the compiler closes over this
What this means, is that by the time your Threads are spawned up the value of i is checked in your UdpPortListener method ... the value of i is the last value in the for loop.. because the loop executed before it.
To fix this .. you need to copy the value inside loop:
var temp = i;
Thread t = new Thread(() =>
{
UdpPortListener(Convert.ToUInt16(52000 + temp));
});
This happens due to closure effect. Try this:
static void Main(string[] args)
{
List<Thread> ts = new List<Thread>();
for(int i = 0; i < 20; i++)
{
var closureIndex = i;
Thread t = new Thread(() =>
{
UdpPortListener(Convert.ToUInt16(52000 + closureIndex));
});
t.IsBackground = false;
ts.Add(t);
}
ts.ForEach((x) => x.Start());
}
The code has 99 problems (just joking) and closure is one of them :). Also you don't need full blown threads you can use tasks.
void static Main()
{
List< System.Threading.Tasks.Task> ts = new List< System.Threading.Tasks.Task>();
for(int i = 0; i < 20; i++) // why not have i = 52000 ???
{
var num = Convert.ToUInt16(52000 + i);
var t = new System.Threading.Tasks.Task(() =>
{
UdpPortListener(num);
});
ts.Add(t);
}
ts.ForEach((x) => x.Start());
}
// Define other methods and classes here
private static void UdpPortListener(UInt16 Port)
{
Console.WriteLine("Listening to port: {0}", Port);
}

Thread synchronization printing strings

I wrote a small programm which prints "x", then "+", then again "x" and so on.
The idea was to make it run in two threads so that the first thread prints "x" and the second prints "+". The output looks like this:
"x" -> Thread number 1
"+" -> Thread number 2
"x" -> Thread number 1enter code here
"+" -> Thread number 2
and so on..
What I wrote seems to work fine but it seems to me it is written in
very old-fashioned way:
public class Example
{
private static int count = 10;
private static int i = 0;
private static bool isOneActive = false;
private static void Run1(object o)
{
string s = o as string;
while(true)
{
if (!isOneActive)
{
Console.WriteLine("Hello from thread number: " +
Thread.CurrentThread.ManagedThreadId + " -> " + s);
isOneActive = true;
if (i++ > count) break;
}
}
}
private static void Run2(object o)
{
string s = o as string;
while(true)
{
if (isOneActive)
{
Console.WriteLine("Hello from thread number: " +
Thread.CurrentThread.ManagedThreadId + " -> " + s);
isOneActive = false;
if (i++ > count) break;
}
}
}
static void Main()
{
Thread t1 = new Thread(Run1);
Thread t2 = new Thread(Run2);
t1.Start("x");
t2.Start("+");
}
I know that now .NET has a lot of instruments for thread synchronization as for example ManualResetEvent class and Task library. So how could we write the same programm using ManualResetEvent class? Is it possible at all?
Your code isn't only old fashioned, it is very inefficient. It spins for no reason doing nothing but waiting; this is called Busy wait should be avoided whenever possible.
Better approach is to use Waithandles as noted in comments.
A naive implementation with very little change in your code will look something like the following.
public class Example
{
private static int count = 10;
private static int i = 0;
private static AutoResetEvent firstEvent = new AutoResetEvent(true);
private static AutoResetEvent secondEvent = new AutoResetEvent(false);
private static void Run1(object o)
{
string s = o as string;
while (true)
{
firstEvent.WaitOne();
Console.WriteLine("Hello from thread number: " + Thread.CurrentThread.ManagedThreadId + " -> " + s);
secondEvent.Set();
if (Interlocked.Increment(ref i) > count)
break;
}
}
private static void Run2(object o)
{
string s = o as string;
while (true)
{
secondEvent.WaitOne();
Console.WriteLine("Hello from thread number: " + Thread.CurrentThread.ManagedThreadId + " -> " + s);
firstEvent.Set();
if (Interlocked.Increment(ref i) > count)
break;
}
}
static void Main()
{
Thread t1 = new Thread(Run1);
Thread t2 = new Thread(Run2);
t1.Start("x");
t2.Start("+");
}
}
Note that firstEvent is instantiated with the initialState flag set to true which means that first thread doesn't waits initially.
Consider this example (fiddle):
static void Main(string[] args)
{
var console = new object();
int i = 0;
Task.Run(() =>
{
lock (console)
while (i++ < 10)
{
Console.Write(i);
Monitor.Pulse(console);
Monitor.Wait(console);
}
});
Task.Run(() =>
{
lock (console)
while (i < 10)
{
Console.Write('+');
Monitor.Pulse(console);
Monitor.Wait(console);
}
});
Console.ReadLine(); // Task.WaitAll might be better, remove for fiddle
}

EF6 linq to sql The context cannot be used while the model is being created

I have to System.Timers.Timer in my application. The intervals of those timers are 1000 and 120000. And each time they tick, they save some entity to database.
But sometimes i get this error in my code; The context cannot be used while the model is being created.This exception may be thrown if the context is used inside the OnModelCreating method or if the same context instance is accessed by multiple threads concurrently. Note that instance members of DbContext and related classes are not guaranteed to be thread safe.
This is my code:
using ACTMULTILib;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace RenderingPlcScanner
{
class Program
{
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
const int SW_HIDE = 0;
const int SW_SHOW = 5;
private System.Timers.Timer timer1 = new System.Timers.Timer();
private System.Timers.Timer timer2 = new System.Timers.Timer();
private GEOTEKRENDERINGEntities grEntities = new GEOTEKRENDERINGEntities();
private ActEasyIF plc = new ActEasyIF();
private bool isUpToDate = true;
private StreamWriter writer;
public Program()
{
grEntities.Database.Connection.Open();
timer1.Interval = 1000;
timer1.Elapsed += timer1_Elapsed;
timer2.Interval = 120000;
timer2.Elapsed += timer2_Elapsed;
....
if (plc.Open() == 0)
{
timer1.Start();
timer2.Start();
}
....
Console.ReadLine();
}
void timer2_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
.....
.....
tblSicakSu tSicakSu = new tblSicakSu();
tSicakSu.Seviye = Math.Truncate(seviye * 100) / 100;
tSicakSu.Sicaklik = Math.Truncate(sicaklik * 100) / 100;
tSicakSu.Tuketim = tuketim[0];
tSicakSu.Zaman = DateTime.Now;
grEntities.tblSicakSu.Add(tSicakSu);
grEntities.SaveChanges();
}
void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
timer1.Stop();
try
{
......
DateTime amin = now.AddMinutes(1);
short[] set = new short[3];
plc.ReadDeviceBlock2("D5010", 3, out set[0]);
//Console.WriteLine(amin.ToString() + " - " + set[0] + "/" + set[1]);
if (amin.Hour == set[0] && amin.Minute == set[1] && !tuketimAlindi)
{
tuketimAlindi = true;
short[] tuketim = new short[5];
plc.ReadDeviceBlock2("D3013", 5, out tuketim[0]);
tblTuketim tTuketim = new tblTuketim();
tTuketim.Zaman = DateTime.Now;
tTuketim.YumusakSu = tuketim[0];
tTuketim.DonusSu = tuketim[2];
tTuketim.SicakSu = tuketim[4];
grEntities.tblTuketim.Add(tTuketim);
grEntities.SaveChanges();
//Console.WriteLine("Tüketim alındı");
}
else if (amin.Minute != set[1])
{
tuketimAlindi = false;
}
short[] data = new short[1];
plc.ReadDeviceBlock2("D4300", 1, out data[0]);
if (data[0] == 0)
{
short[] sayac = new short[1];
plc.ReadDeviceBlock2("D14000", 1, out sayac[0]);
//Console.WriteLine(sayac[0]);
if (sayac[0] > 0)
{
short[] datablock = new short[10];
plc.ReadDeviceBlock2("D15000", 10, out datablock[0]);
short uretimID = datablock[0];
short kazanNo = datablock[1];
short malzeme_kodu = datablock[2];
short malzeme_miktari = datablock[3];
short yil = datablock[4];
short ay = datablock[5];
short gun = datablock[6];
short saat = datablock[7];
short dakika = datablock[8];
short saniye = datablock[9];
var vUretim = (from uretim in grEntities.tblUretim where uretim.PartiNo == uretimID select uretim).ToList();
if (vUretim.Count == 0)
{
tblUretim tUretim = new tblUretim();
tUretim.PartiNo = uretimID;
tUretim.KazanNo = kazanNo;
....
......
grEntities.tblUretim.Add(tUretim);
grEntities.SaveChanges();
short[] value = new short[1];
value[0] = 1;
plc.WriteDeviceBlock2("D4300", 1, ref value[0]);
}
else if (vUretim.Count == 1)
{
tblUretim tUretim = vUretim[0];
....
short[] partiTavukUnuMiktari = new short[1];
.....
grEntities.SaveChanges();
short[] value = new short[1];
value[0] = 1;
plc.WriteDeviceBlock2("D4300", 1, ref value[0]);
}
}
}
}
catch(Exception ex)
{
writer.WriteLine("----------------------------------Error (" + DateTime.Now.ToString() + ") ---------------------------------------------------");
writer.WriteLine(ex.Message + " : " + ex.StackTrace);
writer.WriteLine("-----------------------------------------------------------------------------------------------------------------------------");
writer.Flush();
//Console.WriteLine(ex.Message + " " + ex.StackTrace);
}
timer1.Start();
}
static void Main(string[] args)
{
new Program();
}
}
}
This is happening because the timers are causing multiple threads to access the same instance of your context class, and when the second thread tries to use the class, it is busy still trying to create the model.
You have a couple of options to rectify. The simplest, I think, would be to disable the second timer when the app or form loads, and enable it only after the first iteration of the first timer's code has run.
Alternately, you can have each timer use its own instance of the context.
Or you could catch the exception and exit the method, and wait until the next time around to use the context object.

Categories