[C#] AutoResetEvent Freezing application!

Status
Not open for further replies.

litewarez

Active Member
1,367
2008
1
0
PHP:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.NetworkInformation;
using System.Threading;

namespace SimplePinger
{
    public partial class Form1 : Form
    {
        #region Variables

        int PingAmount = 5;
        AutoResetEvent Waiter = new AutoResetEvent(false);
        Ping pingSender = new Ping();
        PingOptions options = new PingOptions(64, true);
        #endregion

        public Form1()
        {
            InitializeComponent();
            updatePingValue(5); //Set defualt to 5
        }

        private void PingTimes_Scroll(object sender, EventArgs e)
        {
            updatePingValue(PingTimes.Value);
        }

        private void updatePingValue(int Value)
        {
            PingAmount = PingTimes.Value;
            PingAmountLabel.Text = "Pings to send: " + PingAmount;
        }

        private void startPing_Click(object sender, EventArgs e)
        {
            DisableFormElements();
            outputBox.Clear();

            options.DontFragment = true;

            pingSender.PingCompleted += new PingCompletedEventHandler(PingCallback);

            //Create 32 byts to send
            byte[] buffer = Encoding.ASCII.GetBytes("                               ");
            int i;
            for (i = 0; i < PingAmount; i++)
            {


                //Here i want to run this 5 times but without the app freezing :(


                pingSender.SendAsync(addressBox.Text, 120, buffer, options);


            }
            Waiter.WaitOne();
            EnableFormElements();
        }

        public void PingCallback(object sender, PingCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                EnableFormElements();
            }

            if (e.Error != null)
            {
                MessageBox.Show("Ping Failed:" + e.Error.ToString());

                // Let the main thread resume. 
                ((AutoResetEvent)e.UserState).Set();
            }

            PingReply reply = e.Reply;
            Waiter.Set();
            AddCallbackToForm(reply);
        }

        public void AddCallbackToForm(PingReply Reply)
        {
            if (Reply == null)
            {
                return;
            }
            if (Reply.Status == IPStatus.Success)
            {
                outputBox.Text += "Success: " + Reply.Address + " - " + Reply.RoundtripTime + "ms";
            }
            else 
            {
                outputBox.Text += "Failed...";
            }

        }

        public void EnableFormElements()
        {
            startPing.Enabled = true;
            PingTimes.Enabled = true;
        }

        public void DisableFormElements()
        {
            startPing.Enabled = false;
            PingTimes.Enabled = false;
        }
    }
}

here is the Form Class, seems to be freezing / hanging for a while and im sure its something Very stupid but every tutorial that i read shows me that im doing it right :(

Hope you can spot my error :(
 
23 comments
Hello,

You should add some mutex locks in there, since it looks like there is some threading try adding some mutex locks and debug_log messages to check for the errros..

Best of luck...
 
thanks for the advice but i don't think that's the case.

If i remove the Waiter, the applications does not freeze but just throws an error to say that i cant run 2 pings at the same time. So i need the waiter.

If you can show me how to multiple thread it i will give it a go !

ive tried the following just:

PHP:
            for (i = 0; i <= PingAmount; i++)
            {
                Action Action = new Action(() => pingSender.SendAsync(addressBox.Text, 120, buffer, options));
                new Thread(new ThreadStart(Action));
            }

And its stopped hangineg but now the textarea is not being updated :(
 
Once you Multi threaded it you need to follow a guide for mutex locks otherwise your going to get a race condition..
 
pingSender.SendAsync() shouldn't be executed from a new thread since SendAsync will not block the calling thread. It puts it on the thread pool automatically.

Also for a 32 byte buffer:
byte[] buffer = new byte[32];

Finally, get rid of AutoResetEvent. I have never used it, I don't see why you should need it for a simple async ping request.

@Angeix: locks aren't needed here.
 
Am no good with C#

Learning vb.net myself :P mainly good with C++ with past experience with game server emulators :D
 
Thanks hyperz, Ill give it a go after work.. i know what the problem is, i just font know how to fix

when im doing a for loop it sends a command to SendAsync witch in turn starts to do a ping, but because of the for lool the 2 time comes around while the first time is stil running :/.

And yea that 32 byte char i knew it some some thing like that. Thanks
 
I did try that i think

PHP:
int i;
for(i=0;i<=5;i++)
{
    Action Action = new Action(() => pingSender.SendAsync(addressBox.Text,120) )
    new Thread(Action).Start();
}

But still frezed and said that i cannot run another ping request until the previous one has finished
 
Loop inside a new thread, not new threads inside a loop. You only need one thread for this.

Edit: and still you call SendAsync instead of Send...
Edit2: you forgot a ";"
 
i get you, and i havent got C# at work, they wont let me upgrade .NET on the network because they havent checked it or w.e,

Ill try when i get home..

And just for clarification you mean like

PHP:
private void StartButton_Click(......)
{
    ..........

    Action Action = new Action(() => ThreadRunner()); 
    new Thread(Action).Start();
}

public void ThreadRunner()
{
    for(i=0;i<=5;i++)
    {
        pingSender.SendAsync(addressBox.Text,120);
    }
}

:)
 
Code:
private void StartButton_Click(......)
{
    ..........

    new Thread([COLOR=Blue][B]ThreadRunner[/B][/COLOR]).Start();
}

public void ThreadRunner()
{
    for(i=0;i<=5;i++)
    {
        pingSender.[COLOR=Blue][B]Send[/B][/COLOR](addressBox.Text,120);
    }
}
 
Ok does some testing and still not working, it seems to be the callback :(

PHP:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.NetworkInformation;
using System.Threading;

namespace SimplePinger
{
    public partial class Form1 : Form
    {
        #region Variables

        int PingAmount = 5;
        Ping pingSender = new Ping();
        PingOptions options = new PingOptions(64, true);
        byte[] buffer = new byte[32];

        #endregion

        public Form1()
        {
            InitializeComponent();
            updatePingValue(5); //Set defualt to 5

            /*Ping Options*/
            pingSender.PingCompleted += new PingCompletedEventHandler(PingCallback);
        }

        private void PingTimes_Scroll(object sender, EventArgs e)
        {
            updatePingValue(PingTimes.Value);
        }

        private void updatePingValue(int Value)
        {
            PingAmount = PingTimes.Value;
            PingAmountLabel.Text = "Pings to send: " + PingAmount;
        }

        private void startPing_Click(object sender, EventArgs e)
        {
            outputBox.Clear(); /*Fine Here*/
            /*
             * Start the thread to run the InitiateThreadPinger()
             */
            new Thread(InitiateThreadPinger).Start();
        }

        public void InitiateThreadPinger()
        {
            /*
             * Loop 1-10 and run a ping on the host
             */
            options.DontFragment = true;
            for (int i = 0; i <= PingAmount; i++)
            {
                /*
                 * Send the pingSender the Send command with options, Callback attached in Main()
                 * The code in here Executes the correct amount of times as i get the Test below
                 * The problem seems to be that the ping does not execute the callback, Cross Thread Maybe ? ( NO Error Triggered )
                 */
                //MessageBox.Show("Test");
                pingSender.Send("127.0.0.1", 120, buffer, options);
            }
        }

        public void PingCallback(object sender, PingCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                EnableFormElements();
            }
            if (e.Error != null)
            {
                MessageBox.Show("Ping Failed:" + e.Error.ToString());
                return;
            }

            PingReply reply = e.Reply;
            AddCallbackToForm(reply);
        }

        public void AddCallbackToForm(PingReply Reply)
        {
            if (Reply == null)
            {
                return;
            }
            if (Reply.Status == IPStatus.Success)
            {
                outputBox.Text += "Success: " + Reply.Address + " - " + Reply.RoundtripTime + "ms";
            }
            else 
            {
                outputBox.Text += "Failed...";
            }
        }

        public void EnableFormElements()
        {
            startPing.Enabled = true;
            PingTimes.Enabled = true;
        }

        public void DisableFormElements()
        {
            startPing.Enabled = false;
            PingTimes.Enabled = false;
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
    }
}


ive left some comments in there and filtered it down to the callback :( i get no errors so its hard for me to track
 
Use an Action + this.Invoke() in your PingCallback. You should also use break points in visual studio for debugging instead of the javascript-ish MessageBox.Show().
 
Status
Not open for further replies.
Back
Top