Can someone fix this c# code to work correctly in a GUI instead of a console?

I'm trying to get Form1 to show but the 'while' loop under Form1_Load is preventing it from showing.  this is a syslog server code i'm trying to port over to GUI with a lixtbox to add the syslogs it receives.  my only issue right now is getting the form to load up and accessing Listbox1.items.add() .  All of the code is below.

Thanks!

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.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            //Form1 myform = new Form1();
            //myform.ShowDialog();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
           
            //
            IPEndPoint anyIP = new IPEndPoint(IPAddress.Any, 0);
            UdpClient udpListener = new UdpClient(514);
            byte[] bReceive; string sReceive; string sourceIP;

            /* Main Loop */
            /* Listen for incoming data on udp port 514 (default for SysLog events) */
            while (true)
            {
                try
                {
                    bReceive = udpListener.Receive(ref anyIP);
                    /* Convert incoming data from bytes to ASCII */
                    sReceive = Encoding.ASCII.GetString(bReceive);
                    /* Get the IP of the device sending the syslog */
                    sourceIP = anyIP.Address.ToString();
                    new Thread(new logHandler(sourceIP, sReceive).handleLog).Start();
                    /* Start a new thread to handle received syslog event */
                }
                catch (Exception ex) { Console.WriteLine(ex.ToString()); }
            }
            


        }
      
            
           
        

        class logHandler
        {
            /* Phrases within the syslog that will trigger an email notification */
            private string[] emailTriggers = new string[] { "link loss", "help please" };
            private string outputPath = @"C:\syslog_c#\syslog.csv"; /* Location to store events */
            private string source; private string log;

            public logHandler(string sourceIP, string logData) /* Initialize object and clean up the raw data */
            {
                source = sourceIP.Trim(); /* Client IP */
                log = logData.Replace(Environment.NewLine, "").Trim(); /* Syslog data */
            }

            public void handleLog() /* Store the syslog and determine whether to trigger an email notification */
            {
                /* Store the syslog using a new thread */
                new Thread(new outputCsvRow(outputPath, new string[] { source, log }).addRow).Start();
                //for (int i = 0; i < emailTriggers.Count(); i++) { if (log.Contains(emailTriggers[i])) { emailEvent(); } }
                /* Search for trigger strings and send email if found */

                return;
            }

            //private void emailEvent() /* Send email notification */
            //{
            //    try
            //    {
            //        MailMessage notificationEmail = new MailMessage();
            //        notificationEmail.Subject = "SysLog Event";
            //        notificationEmail.IsBodyHtml = true;
            //        notificationEmail.Body = "<b>SysLog Event Triggered:<br/><br/>Time: </b><br/>" + 
            //            DateTime.Now.ToString() + "<br/><b>Source IP: </b><br/>” + 
            //            source + “<br/><b>Event: </b><br/>" + log; /* Throw in some basic HTML for readability */
            //        notificationEmail.From = new MailAddress("SysLog@metastruct.com", "SysLog Server"); /* From Address */
            //        notificationEmail.To.Add(new MailAddress("metastructblog@gmail.com", "metastruct")); /* To Address */
            //        SmtpClient emailClient = new SmtpClient("10.10.10.10"); /* Address of your SMTP server of choice */
            //        //emailClient.UseDefaultCredentials = false; /* If your SMTP server requires credentials to send email */
            //        //emailClient.Credentials = new NetworkCredential(“username”, “password”); /* Supply User Name and Password */
            //        emailClient.DeliveryMethod = SmtpDeliveryMethod.Network;
            //        emailClient.Send(notificationEmail); /* Send the email */
            //    }
            //    catch (Exception ex) { Console.WriteLine(ex.ToString()); }
            //    return;
            //}
        }
        class outputCsvRow : Form
        {
            private string formattedRow = null;
            private string outputPath = null;

            public outputCsvRow(string filePath, string[] columns) /* Initialize object */
            {
                outputPath = filePath;
                formattedRow = (char)34 + DateTime.Now.ToString() + (char)34; /* Construct csv row starting with the timestamp */
                for (int i = 0; i < columns.Count(); i++) { formattedRow += "," + (char)34 + columns[i] + (char)34; }
            }

            public void addRow()
            {
                int attempts = 0;
                bool canAccess = false;
                StreamWriter logWriter = null;
                if (!File.Exists(outputPath)) /* If the file doesn't exist, give it some column headers */
                {
                    logWriter = new StreamWriter(outputPath, true);
                    logWriter.WriteLine((char)34 + "Event_Time" + (char)34 + "," +
                      (char)34 + "Device_IP" + (char)34 + "," + (char)34 + "SysLog" + (char)34);
                    logWriter.Close();
                }
                /* Thread safety first! This is a poor man's SpinLock */
                while (true)
                {
                    try
                    {
                        logWriter = new StreamWriter(outputPath, true); /* Try to open the file for writing */
                        canAccess = true; /* Success! */
                        break;
                    }
                    catch (IOException ex)
                    {
                        if (attempts < 15) { attempts++; Thread.Sleep(50); }
                        else { Console.WriteLine(ex.ToString()); break; } /* Give up after 15 attempts */
                    }
                }
                if (canAccess) /* Write the line if the file is accessible */
                {
                   
                   //myform.Show;
                    
                    logWriter.WriteLine(formattedRow);
                    logWriter.Close();
                    
                    //Form1.listBox1.Items.Add(formattedRow);
                }
                return;
            }
        }


    }
}

Open in new window

linuxroxAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

d_yorkCommented:
Hi!  The reason your UI isn't updating is because when it loads the form you're firing up a udp listener in 'synchronous' mode - using udpListen.Receive() is going to hang the app in that while loop forever because as soon as it finishes processing it'll go back to listening.  It's doing that all on the same thread as the UI.  You've got a couple options:
1)  Do it with a BackgroundWorker - that'll get it off your main UI thread
2)  Use udpListen.BeginReceive() and handle the event it'll fire when it receives data.  This is "asynchronous" meaning it'll keep working and let your UI update and be clickable and stuff
3)  Create a new Thread and put your listener and stuff in that Thread.  Create a Delegate for the Thread to call to update the listbox.

If it were me, not knowing the details, I'd probably be inclined to do the work with a BackgroundWorker.

You will also benefit from using Delegates to update your GUI.  https://msdn.microsoft.com/en-us/library/aa288459(v=vs.71).aspx is kind of a wordy example, but you can Google C# Delegates to see some examples of how to use a Delegate to update your GUI from another thread.  The BackgroundWorker will help you here, it can do this for you.

There's no way around this, you are going to have to make a change around how you are listening for udp messages, you can't do that synchronously on the same thread as the GUI - it can only do one thing at a time and you've asked it to first listen forever for udp messages so it'll never reach the point where it'll draw the form.
0
linuxroxAuthor Commented:
I see.  i'm new to c# so trying to learn.  Thanks and i'll take a look at what you've shown me here so maybe I can get this thing to work!  thanks again!
0
d_yorkCommented:
Anytime, I understand how it is.  I like BackgroundWorker for stuff like this - I can give you code samples but rewriting your app for you won't help you learn  :)  You'll find it isn't difficult at all to use and you'll be able to reuse a lot of your methodology.  I'm assuming this has been working for you as a console app, no huge number of threads being spawned and mysterious "this application has stopped responding".   So if you want to reuse a lot of you code, from the toolbox drag a BackgroundWorker object onto your form.  In properties for BackgroundWorker go ahead and set 'Reports Progress' to true, you'll need that.  Then go to Events and you'll see the BackgroundWorker does three things:
DoWork - doubleclick and it'll create a function for this event which is where you're going to put the code for listening to UDP messages (your while loop).
ProgressChanged - because you set it to 'Reports Progess = true' this function can be called anytime by you to report progress.  It takes two arguments, and the second argument is super useful - it's an object so it can be anything like the UDP data you've received or whatever (maybe the result from your parsing of the udp message?).
WorkerCompleted - this one is for cleanup and final last minute tasks.  If you set the BackgroundWorker properties to 'Supports Cancellation = true', then this also gets called if the background operation is cancelled.

That's it - the ProgressChanged event will talk to your GUI just fine without any special delegates.  You could, for example, do something like this:
//Do Work
private void backgroundWorker1_DoWork(obect sender, DoWorkEventArgs e)
{
     //here you're listening for udp data with a while loop
    //maybe what you do here is spawn your loghandler threads when it comes in and go back to listening
    //or - you could use the ReportProgress to pass the data you want to process
    backgroundWorker1.ReportProgress(0, sourceIP+"*"+sReceive)  //we'll split the string on *
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressEventArgs e)
{
     string args[] = ((string)e.UserState).Split('*');
     //args[0] is your source ip, args[1] is your sReceive
     //here you'll do that loghandling stuff
     //or maybe here you'll have another backgroundworker fire up
     //or you'll format your stuff and update your listbox
    Form1.listBox1.Items.Add(formattedRow);
}
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
linuxroxAuthor Commented:
oh thank you!  yes samples are great and i love this stuff!!  it's so addictive for me.  i started off with VB6 and my jobs have moved me over into php/mysql and whatnot but i dabble in a bit of everything...borland delphi 7 and such.  but my life now doesn't allow me to really focus on anything in particular.   just no time for it but when i get on a project i really love to dig into it and learn as much as i can.  The reason i even started this project for a syslog server is because we need it to log WIFI connections and problems and i found some src code for a console c# syslog server and adapted it a bit to work for me and it works perfectly as a console but i just want to make it into a GUI and possibly let others have it for free because the other GUI programs out there as a free version only allow like 10 or 15 connections to the server...that's lame.  i can dish one out for free that accepts unlimited.  just isn't cost affective for most to have something that achieves a very simple goal.  to me it's like you are paying for unlimited connections to a socket!?!?!  wtf!  no way dude.  not in my world!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.