Click here to Skip to main content
15,898,373 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello,

I have a form based application in which i want to update the contents of a form when an event occurs so i tried out two things:
1) Started a thread which will continuously monitor if an event has been detected or not? if event has occurred then the contents of the form will be updated. This process is continuously taking place.
2) Started a Timer which in which on every tick the event is monitored.

The problem is that both these methods are causing the application to hang. A white screen appears and the form gets hanged. So i need to do such a thing where i can do all the operations in a form and parallel processing in the background takes place.

Thanks a lot
Posted
Comments
OriginalGriff 19-Dec-13 5:07am    
What kind of "event" are you talking about?
How do you detect that it occurred?
Rahul VB 21-Dec-13 4:38am    
Hello Sir,

I am working on a PLC product. My aim is to monitor a sensor event controlled by PLC. I am reading the memory registers of the plc device. Due to this i will come to know that an event has occurred or not. So i am continuously polling the registers after every second, because i want to make it real time. The moment an event occurs for example : motion detection,fire alarm etc then my application should know this.

So i started the timer on form load i.e in form_load().
The flow is :

1)On form load start a timer/ thread
- If i use a timer,then after tick perform steps 2 to 4.
- If i use a thread then start the thread in background which will perform the steps 2 to 4 repeatedly.
2)connect to the plc socket.
3)Now send a request to read the memory location which has sensor data.
4)Receive the data. Compare which type of event has occured? According to the event update the form.
5) Finally disconnect the socket.


My code is all messed up, please have a look:




public Form1()
{
InitializeComponent();
try
{
net = new Network("172.16.3.230");
status = net.InitConnection();////initializing socket connection
if (status)
this.Load += new EventHandler(Form1_Load);
}
catch(SocketException e)
{
MessageBox.Show(e.Message + ". This application wont work further, please conenct the LAN cable and then check again. WARNING: The next screen will load but nothing will operate.");

}


}

private void Form1_Load(object sender, EventArgs e)
{
st = new sensorState(); //// this class contains the status of sensors to be compared
time = new Timer();
time.Enabled = true;
time.Interval = 1000;
time.Tick += new EventHandler(time_tick);
}


public void time_tick(object sender, EventArgs e)
{
try
{
net.send(st.create_read_packet()); // send a read packet

if ((net.receive())[9] == 0x02 )
{
MessageBox.Show("Terrace door sensor detected");

}

if ((net.receive())[9] == 0x80)
{
MessageBox.Show("Beam Detector2 detected");

}



if ((net.receive())[10] == 0x40)
{
MessageBox.Show("Beam detector1 event");

}

if ((net.receive())[11] == 0x02)
{

MessageBox.Show("Smoke Detected");
}



if ((net.receive())[12] == 0x04)
{
MessageBox.Show("LPG gas leak detected");

}



}
catch(SocketException e1)
{
MessageBox.Show(e1.Message.ToString());
}

}


May be i am adding too much on form load. I just also want to know that is my architecture correct?
Because later i am also planning to give a web interface to my client.

Thanks
Hammad 19-Dec-13 5:10am    
which type of event...? and change on the same form or another. clear you need
Alexander Dymshyts 19-Dec-13 5:24am    
Do you use mvvm pattern?
bholey 19-Dec-13 6:03am    
Plz show ur code so that we can understand the actual reason for hang.

1 solution

The way I would handle this is to use a thread, not a timer, and to establish a connection and maintain it until the application closes: don't open and close the connection, keep it open.

Probably, I would misuse a BackgroundWorker and it's ReportProgress event to transfer an enum value indicating the status.
C#
public enum ResponseCode
   {
   None,
   TerraceDoorSensor,
   BeamDetector2,
   BeamDetector1,
   SmokeDetected,
   LPGGasLeakDetected,
   Unknown,
   }

Create a class level bool called exitNow, and create the background worker:
C#
BackgroundWorker work = new BackgroundWorker();
work.WorkerReportsProgress = true;
work.ProgressChanged += new ProgressChangedEventHandler(work_ProgressChanged);
work.DoWork += new DoWorkEventHandler(work_DoWork);
exitNow = false;
work.RunWorkerAsync();


The background worker sits in a loop:
C#
void work_DoWork(object sender, DoWorkEventArgs e)
    {
    BackgroundWorker work = sender as BackgroundWorker;
    if (work != null)
        {
        // Open the connection
        net = new Network("172.16.3.230");
        net.InitConnection();
        while (!exitNow)
            {
            net.send(st.create_read_packet());
            int deviceResponse = net.receive()[9];
            ResponseCode status = ResponseCode.None;
            switch (deviceResponse)
                {
                default: status = ResponseCode.Unknown; break;
                case 0x02: status = ResponseCode.TerraceDoorSensor; break;
                case 0x80: status = ResponseCode.BeamDetector1; break;
                ...
                }
            work.ReportProgress((int) status);
            System.Threading.Thread.Sleep(500);
            }
        //Close the connection.
        ...
        }
    }

And the report progress event does the display:
C#
void work_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
    ResponseCode status = (ResponseCode)e.ProgressPercentage;
    switch (status)
        {
        case ResponseCode.None: break;
        case ResponseCode.BeamDetector1: MessageBox.Show("Beam detector1 event"); break;
        ...
        }
    }
(Though I'd probably not use a MEssageBox!)
When you close your app, in your FormClosing event you set exitNow to true to allow the worker to die naturally.
 
Share this answer
 
Comments
Rahul VB 21-Dec-13 12:53pm    
Hello Sir,
Thanks a lot. I will have to read up a lot about threading. And really, this has helped me thanks a lot.
Rahul VB 22-Dec-13 5:47am    
Hello Sir,
I tried keeping the connection open, but the thing is that i am unable to send 3 hex byte packets at a time one after another to the PLC. So after sending a packet i reinitialize the connection.

1-> send a packet, close the connection.
2-> Reinitialize the socket to send the data again.i.e initialize the socket constructor and start off again.
In this case what should i do?

Thanks
OriginalGriff 22-Dec-13 5:57am    
"i am unable to send 3 hex byte packets at a time one after another"
Why not? What happens when you try?
Rahul VB 22-Dec-13 12:47pm    
Hello sir,

There are 3 things to be done on the plc server unit:
1)Write a memory coil, once written an alarm will start on the plc indicating that a sensor event has been detected.
2)Now send a packet to the server which will contain the description about the sensor event detected.
3)send the mobile number to the server unit, because then the server will send a message to the customer telling him that some emergency has occured.

Now if i send all the three packets like this:
socket.send(coil);
socket.send(message);
socket.send(mobile);

In this case only the first 2 packets delivered to the PLC even though i am sending the last packet.
So what i do is:
1-> After sending the first 2 packets :
socket.Disconnect(true);
socket.close()
socket sck = new socket();
sck.connect(endpoint);
sck.send(mobile);

I have not used asynchronous sockets. Is it necessary in this scenario? Please guide.

Thanks
OriginalGriff 23-Dec-13 5:28am    
I would suspect that the problem is pretty simple: the PLC is busy.
Normally, I would expect to get a "got that, ok" type signal back from the PLC to indicate it is ready. Check if there is a response to each of those messages, and then wait for it from the PLC before sending the next (I'd also introduce a timeout so I can resend the original message if I don;t get an "OK" response.)
If you just send, send, send then you probably aren't giving it enough time to finish what it is doing and get ready for a new message.

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