Hi, and welcome to my first post on any forum!
I'm a LabVIEW developer by trade, and have begun an attempt to learn C# as I have heard many praises.
My biggest problem at the moment, is being able to update the UI while the program is working.
All my App does, is ping a list of PC's and return the time or it's success. Unfortunately, the example that I have written, does not do this.
The UI is kept stagnant until it has completed all it's tasks. WHY!? This HAS to be a noob mistake, but for the life of me I can't see where it is coming from. Do I have to create a seperate UI thread!? Surely this is too advanced. What about the BackgroundWorker stuff?
using System; using System.IO; 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.NetworkInformation; namespace MESNetworkAnalyser { public partial class MainForm : Form { private string[] computerList; BackgroundWorker bw = new BackgroundWorker(); public MainForm() { InitializeComponent(); bw.WorkerSupportsCancellation = true; bw.WorkerReportsProgress = true; } private void MainForm_Load(object sender, EventArgs e) { computerList = Read_Computer_List("computerList.txt");
int inc = 0; foreach (string computer in computerList) { computerList.SetValue(computer.Trim(),inc); inc++; } ProgressText.Lines = computerList; } private void bw_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker worker = sender as BackgroundWorker;
} private string[] Read_Computer_List(string fileName) { StreamReader sr = new StreamReader(fileName); string fileContents = sr.ReadToEnd(); string[] fileLines = fileContents.Split(new char[] {'\n'}); return fileLines; } private string ping(string computerName) { computerName.Trim(); Ping pingSender = new Ping(); PingOptions options = new PingOptions(); // Use the default Ttl value which is 128, // but change the fragmentation behavior. options.DontFragment = true; // Create a buffer of 32 bytes of data to be transmitted. string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; byte[] buffer = Encoding.ASCII.GetBytes(data); int timeout = 120; try { PingReply reply = pingSender.Send(computerName, timeout, buffer, options); if (reply.Status == IPStatus.Success) { return string.Concat("RoundTrip time: ", reply.RoundtripTime); } else { return "No Connection"; } } catch { return "No Connection"; } } private void StartButton_Click(object sender, EventArgs e) { int inc = 0; int listSize = computerList.Length; int successCounter = 0; foreach (string computer in computerList) { string pingReply = ping(computer); string[] tempArray = ProgressText.Lines; tempArray[inc] = String.Concat(computer, "...", pingReply); ProgressText.Lines = tempArray; if (!pingReply.Equals("No Connection")) { successCounter++; } inc++; totalProgressBar.Value = inc / listSize * 100; Thread.Sleep(1000); } ResultsText.Text = String.Concat(successCounter, "/", listSize, " computers were found on the network"); } } }
|
Steve DayusPosted Nov 30, 2009, 3:30 PM
using System;
using System.IO;
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.Threading;
using System.Net.NetworkInformation;
using System.Reflection;
namespace MESNetworkAnalyser
{
public partial class MainForm : Form
{
private string[] computerList;
//BackgroundWorker bw = new BackgroundWorker();
public MainForm()
{
InitializeComponent();
//bw.WorkerSupportsCancellation = true;
//bw.WorkerReportsProgress = true;
}
private void MainForm_Load(object sender, EventArgs e)
{
computerList = Read_Computer_List("computerList.txt");
int inc = 0;
foreach (string computer in computerList)
{
computerList.SetValue(computer.Trim(), inc); inc++;
}
ProgressText.Lines = computerList;
}
// remove this and add backgroundworker control to form
//
//private void bw_DoWork(object sender, DoWorkEventArgs e)
//{
// BackgroundWorker worker = sender as BackgroundWorker;
//}
private string[] Read_Computer_List(string fileName)
{
StreamReader sr = new StreamReader(fileName);
string fileContents = sr.ReadToEnd();
string[] fileLines = fileContents.Split(new char[] { '\n' });
return fileLines;
}
private string ping(string computerName)
{
computerName.Trim();
Ping pingSender = new Ping();
PingOptions options = new PingOptions();
// Use the default Ttl value which is 128,
// but change the fragmentation behavior.
options.DontFragment = true;
// Create a buffer of 32 bytes of data to be transmitted.
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 120;
try
{
PingReply reply = pingSender.Send(computerName, timeout, buffer, options);
if (reply.Status == IPStatus.Success)
{
return string.Concat("RoundTrip time: ", reply.RoundtripTime);
}
else { return "No Connection"; }
}
catch { return "No Connection"; }
}
private void StartButton_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
totalProgressBar.Value = e.ProgressPercentage;
totalProgressBar.Refresh();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
ResultsText.Text = String.Concat(successCounter, "/", listSize, " computers were found on the network");
}
// Move Variables Up a Scope To Make Background Worker Complete fire ok!
int listSize;
int successCounter;
int inc;
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
inc = 0;
listSize = computerList.Length;
successCounter = 0;
foreach (string computer in computerList)
{
string pingReply = ping(computer);
string[] tempArray = ProgressText.Lines; tempArray[inc] = String.Concat(computer, "...", pingReply);
SetControlPropertyThreadSafe(ProgressText, "Lines", tempArray);
//ProgressText.Lines = tempArray;
if (!pingReply.Equals("No Connection"))
{
successCounter++;
}
inc++;
int alue = (inc * 100)/ listSize ;
backgroundWorker1.ReportProgress((inc * 100) / listSize); // Increase ProgressBar using Background worker reportProgress
Thread.Sleep(1000);
}
// ResultsText.Text = String.Concat(successCounter, "/", listSize, " computers were found on the network");// moved to Backgroundworker Complete
}
// This will make it possable to make updates on UI Thread
private delegate void SetControlPropertyThreadSafeDelegate(Control control, string propertyName, object propertyValue);
public static void SetControlPropertyThreadSafe(Control control, string propertyName, object propertyValue)
{
if (control.InvokeRequired)
{
control.Invoke(new SetControlPropertyThreadSafeDelegate(SetControlPropertyThreadSafe), new object[] { control, propertyName, propertyValue });
}
else
{
control.GetType().InvokeMember(propertyName, BindingFlags.SetProperty, null, control, new object[] { propertyValue });
}
}
}
}
AndrewPosted Jul 11, 2009, 7:39 PM
I remain baffled that I need to have a seperate thread when all I want to do is update the UI. Surely even "Hello World" applications need this same feature!? I was under the impression that developers (even with experience) avoid thread handling since it is confusing.
All that aside. I still don't understand what part of the code is asynchronous? It is a simple synchronous program. 2 things are NOT happening at the same time.
1. Ping computer
2. Get reply
3. Update UI with result
4. Repeat
In exactly that order. I can't have the pinging in a seperate thread to the UI updates as I won't know if the reply is back yet! Or for which computer!
I feel that I am missing the point completely on this one, so I would be most appreciative if someone could explain why this SIMPLE 4 step process can't be achieved in C# without needing the skills of a C# highlander.
Thanks in andvance
Bechir BejaouiPosted Jul 11, 2009, 6:38 PM
imagine the method that do the ping is void and parameterless
void method(){bla bla bla}
you do as follow
public delegate void DELEG();
in the core program
DELEG deleg = new DELEG(method);
IAsynkResult result = deleg.BeginInvoke();
some code here in parallel execution
deleg.EndInvoke(result);