Click here to Skip to main content
15,868,016 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hello everyone,
I have a problem and i need help in something,

I am developing a software based on c#.net that will generate a QR ticket through and EPSON printer, and that ticket is supposed to be in enrolled a 3 ZKteco access control panel to be used only one time and the ticket will get removed from the whitelist of the ZKteco access control panels.


The problem is that the tasks was overlapping, so i used the lock feature which fixed the overlapping a little bit, the time of the tasks are no longer deterministic.

I need help how to get out this, also i had an idea but i don't know how to implement it which was to create a thread scheduler which will prevent overlapping and when the task is triggered to run it will be added to a FIFO queue and the task manager will run the task from it accordingly

What I have tried:

so i mainly have 2 tasks;
1- Generate Ticket and Enroll user to access control
2- Check logs and if enrolled tickets are used remove them

Task 1 is initiate when the user presses a button by the following implementation,
private void button7_Click(object sender, EventArgs e)
{
    {
        Generated_tickets_Counter.Increment();
        Visitor.Generate_Ticket(Visitor.Generate_VisitorID(Generated_tickets_Counter.Count));
        pictureBox6.Image = Visitor.QRcodeImage;

        Printer = new TicketPrinter("جمعية الهلال الأحمر", Visitor.complete_zeros(Generated_tickets_Counter.Count.ToString(), 3), Visitor.QRcodeImage);

        var item = GetItem(Visitor);
        IDbuffer = item.Value;
        //create List of string
        var ips = DB_Handler.GetIPlist();

        Pins.Add(Generated_tickets_Counter.Count.ToString());
        timer1.Enabled = true;

        System.Threading.Thread t = new Thread(x => EnrollIps(ips, item));
        t.Start();
    }
}



private void EnrollIps(List<string> ips, KeyValuePair<int, string> item)
{
    lock (mutex)
    {
        foreach (var ip in ips)
        {

            ACManager.Connect(ip, "4370");
            ACManager.EnrollUser(item.Key.ToString(), item.Value);
            ACManager.Disconnect();
        }

        var dlgt = new dlgtAfterEnrollIps(AfterEnrollIps);
        this.Invoke(dlgt, new object[] { item.Key, item.Value });
    }
}


private void AfterEnrollIps(int key , string value)
 {
         Printer.Print_Ticket();

         label_counter.Text = Visitor.complete_zeros(Generated_tickets_Counter.Count.ToString(), 3);
         DateTime current_datetime = DateTime.Now;
         if (Generated_tickets_Counter.Count == 1)
         {
             DB_Handler.Add_log(current_datetime.ToShortDateString(), Username, Generated_tickets_Counter.Count.ToString(), "0");
         }
         if (Generated_tickets_Counter.Count > 1)
         {
             DB_Handler.Update_GenTickets(Generated_tickets_Counter.Count.ToString(), current_datetime.ToShortDateString());
         }

         AccessControl._values.Add(key, value);
         label_status.Text = "Visitor Successfully Created";
         DB_Handler.Add_Ticket(IDbuffer, Username);
     //Add the ticket to Database HERE

 }


and Task2 periodic every 12s
private void timer1_Tick(object sender, EventArgs e)
{
    System.Threading.Thread t = new Thread(x => handleTimer());
    t.Start();
}


private void handleTimer()
{
    var ips = DB_Handler.GetIPlist();
    DateTime current_datetime = DateTime.Now;

        foreach (var ip in ips)
        {
        var logs = new List<LogItem>();
        lock (mutex)
        {
            ACManager.Connect(ip, "4370");
            logs = ACManager.GetLogs(false);
            ACManager.Disconnect();
        }
            foreach (var user in AccessControl._values)
            {
                if (logs.Any(x => x.Pin == user.Key && x.Cardno == Convert.ToInt64(user.Value)))
                {
                    var items = logs.Where(x => x.Pin == user.Key);
                    foreach (var address in ips)
                    {
                        lock (mutex)
                        {
                            ACManager.Connect(address, "4370");
                            ACManager.RemoveUser(user.Key.ToString());
                            ACManager.Disconnect();
                        }
                    }
                    Used_tickets_Counter.Increment();
                    DB_Handler.Remove_ticket(user.Value.ToString(), Username);
                    DB_Handler.Update_UsedTickets(Used_tickets_Counter.Count.ToString(), current_datetime.ToShortDateString());
                    break;
                }
            }
        }



    var dlgt = new dlgtAfterHandleTimer(AfterHandleTimer);
    this.Invoke(dlgt);
}
Posted
Comments
[no name] 27-Aug-22 13:55pm    
Go ahead and add a concurrent queue.

https://docs.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentqueue-1?view=net-6.0
Member 15627495 29-Aug-22 11:36am    
you need to sinchronize your task call/ or to wait for their response

with thread and tasks, you have : join() and wait() to make them working 'synchronous'.


the 'hash' of a thread is a solid tool, to identify them with lot of 'creation/destructions'.
by an array of tasks ... and few status datas, you can build a better handle of your tasks.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900