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 databaseif there are data which should be sentadd the data to the queueif queue is not emptysend the next message and remove it from the queuesleep 10 secondsif a message from another thread arrivedstop waiting and go to next message in queueif no message from another thread arrivedgo back to the first step, but do this only 2 timesif a message still hasn't arrived from another threadpass to the next message until queue is emptyreturn to the first stepI 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?
Database threading design
c#;multithreading;thread safety