I am new to threading and I am a junior developer, so I guess there are many mistakes. My scenario is this:
- look into the database
- if there are data which should be sent
- add the data to the queue
- if queue is not empty
- send the next message and remove it from the queue
- sleep 10 seconds
- if a message from another thread arrived
- stop waiting and go to next message in queue
- if no message from another thread arrived
- go back to the first step, but do this only 2 times
- if a message still hasn't arrived from another thread
- pass to the next message until queue is empty
- return to the first step
I am trying to do this like this:
private Thread ReceiveThread;
private Thread SendThread;
internal static Thread ServiceThread;
These 3 threads:
ReceiveThread = new Thread(ReceiveTask);
ReceiveThread.Start();
ServiceThread = new Thread(SerAutoThread.SendServiceMsg);
ServiceThread.Start();
SendThread = new Thread(SendTask);
SendThread.Start();
class SerAutoThread
{
internal static object[] NextService;
public static readonly object _locker = new object();
internal static Queue<object[]> Services;
internal static int sendingTime = 0;
private static DatabaseFirebird DB;
internal static void SendServiceMsg()
{
DB = new DatabaseFirebird();
DB.Open(ConnectionStr);
Services = new Queue<object[]>();
while (true)
{
if (Services.Count != 0)
{
SetNextSerAndSend();
}
else
{
CheckAndSetServices();
}
}
}
private static void SetNextSerAndSend()
{
NextService = Services.Dequeue();
for (int j = 0; j < 4; j++)
{
if (sendingTime == TRANSMITTED)
{
//pass to next msg
sendingTime = 0;
j = NEXTMSG;
}
else if (sendingTime < 3)
{
sendingTime++;
Byte[] data = SetNextPckage();
DeviceManager.MessageSendQueue.PostItem(new SendMessage("UDPCmd",
NextService[(int)NextMsg.DeviceId].ToString(),
data, data.Length));
MyDebug.WriteLine("Sended...");
lock (_locker)
{
Monitor.Wait(_locker, TimeSpan.FromSeconds(10));
}
}
else
{
// pass to next msg
j = NEXTMSG;
}
}
}
}
private void ReceiveTask()
{
ReceiveMessage receiveMsg;
while (true)
{
receiveMsg = Com.MessageReceiveQueue.GetItem(-1);
SerAutoThread.sendingTime = SerAutoThread.TRANSMITTED;
lock (SerAutoThread._locker)
{
Monitor.Pulse(SerAutoThread._locker);
}
}
}
private void SendTask()
{
SendMessage msg;
while (true)
{
msg = MessageSendQueue.GetItem(-1);
String rtrn = PushData(msg);
}
}
Is this thread-safe or not? I'm not sure if something is wrong with the design or I'm doing something wrong elsewhere.
And this is not my entire code (for understanding). When I actually run the app, this works fine. Yesterday just ones my Database management system (Firebird) locked. Then I stopped my app, stopped Firebird server then started again and ran my app again. Now it is ok again. I am not using threads with deep understanding. So I am worried about thread safety.
Is it possible for the thread-locked Firebird?