custom event

W

websmurf

dear newsgroup member,

I want to access a label in a form (form1.cs) from a class file
(periodicUpload.cs). The label in form1.cs is a status Indicator.
PeriodicUpload.cs is a timer class file. From this class file I upload every
minute a file to a web server. in the Main form (form1.cs) the label must
changed when an error occurs in PeriodicUpload.cs.

I read something about delegate and event but I don't know how to implement
this.
I am just start with programming with c#.

can some one help me with this please
 
M

Marc Gravell

What do you mean "PeriodicUpload.cs is a timer class file"?

Essentially, there are a handful of ways of doing a periodic upload.
The simplest (and most appropriate if you are starting) is simply to
drop a win-form Timer control onto your form1, with a duration of 1
minute, and handle the Tick event. In the designer you can wire this
up by just double-clicking on the Timer.

You would also need to add a try/catch around the upload, and update
the label (with the error message) in the "catch".

This isn't the /absolute/ best approach (it would be better to do the
upload on a worker thread), but if you are new to C# it is a
reasonable first attempt; otherwise you will get distracted into
oddities like thread-affinity, callbacks, etc.

Marc
 
W

websmurf

Hi Marc,

Thx for your reply. But this timer tick event occurs in the class file
"PeriodicUpload.cs" and not on the form1.cs. I have also a try and catch
block
where i fire the event for the label. But I am doing something wrong en get
the warning message "Illegal Cross Thread Calls" in VS2005. I get this
because I have send the form1 object as a parameter to the constructor of
PeriodicUpload and this is not the approperiate way to do so in VS2005. What
i want to know is, how to do it with delegate and events.

I will add the source file here: look at "WebStatGen" in periodicUpload.cs
this not the appropriate way to do this in VS2005

Form1.cs source file:
----------------------------------------------------
using System;
using System.IO;
using FtpLib;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WinWebQ
{
public partial class WebStatGen : Form
{
public static string llabel;
PeriodicUpload periodicUpload = null;
public WebStatGen()
{
InitializeComponent();
FtpConfigManager fcm = new
FtpConfigManager(Application.StartupPath);
periodicUpload = new PeriodicUpload(fcm.create() ,
@"c:\yoyo\cms_stats\CSV_test.html", this);
}


private void button1_Click(object sender, EventArgs e)
{

}

private void label1_Click(object sender, EventArgs e)
{

}

private void btn_Start_Click(object sender, EventArgs e)
{
btn_Stop.Enabled = true;
btn_Start.Enabled = false;
periodicUpload.Start();

}

private void fTPConfigToolStripMenuItem_Click(object sender,
EventArgs e)
{
FTP_Options FTP_Form = new FTP_Options();
FTP_Form.ShowDialog(this);
FtpConfigManager ftpConfigFactory = new
FtpConfigManager(Application.StartupPath);
FTPConfig fc = ftpConfigFactory.create();
periodicUpload.changeCongifuration(fc);
}

private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
WebStatGen Gen_Form = new WebStatGen();
Application.Exit();
}
public void Statusss(int status)
{
if (status == 0)
{
this.label2.Text = "Status OK";
this.label2.ForeColor = System.Drawing.Color.Green;
}
else
{
this.label2.Text = "Status NOK";
this.label2.ForeColor = System.Drawing.Color.Red;
}
}
private void btn_Stop_Click(object sender, EventArgs e)
{
btn_Stop.Enabled = false;
btn_Start.Enabled = true;
periodicUpload.Stop();

}
}
}
---------- End form1.cs --------------------------------

PeriodicUpload.cs
--------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Timers;
using FtpLib;

namespace WinWebQ
{
class PeriodicUpload
{
private static FTPFactory ff;
private Timer timer = null;
private static String fileToUpload = null;
private FTPConfig config;
private static WebStatGen gg; // object call

private static void TimerEventHandler( object source,
ElapsedEventArgs e )
{
readInputFile rif = new readInputFile();
rif.readfile();

try
{
gg.Statusss(1);
ff.upload(fileToUpload);
}
catch (Exception)
{
gg.Statusss(1);

ff.setRemoteHost("ftp.casblokker.nl");
ff.setRemoteUser("wicom");
ff.setRemotePass("12345");
ff.login();
ff.chdir("../WebQ");
ff.setBinaryMode(true);

ff.upload(fileToUpload);
}
}

public PeriodicUpload(FTPConfig _config, String _fileToUpload,
WebStatGen _gg)
{
config = _config;
gg = _gg;
fileToUpload = _fileToUpload;
InitFTP();
InitTimer();
}

public void changeCongifuration(FTPConfig _config)
{
config = _config;
timer.Interval = config.timeout;
}

private void InitTimer()
{
timer = new Timer();
timer.Elapsed += new ElapsedEventHandler(TimerEventHandler);
timer.Interval = config.timeout;
}


public void Start()
{
ff.setRemoteHost(config.hostname);
ff.setRemoteUser(config.username);
ff.setRemotePass(config.password);
ff.login();
ff.chdir(config.remotedir);
ff.setBinaryMode(true);
timer.Start();
timer.Enabled = true;
}

private static void InitFTP()
{
ff = new FTPFactory();
ff.setDebug(true);

}

public void Stop()
{
timer.Enabled = false;
ff.close();
}
}


}

------------- End PeriodicUpload.cs ---------------
 
K

KWienhold

Hi Marc,

Thx for your reply. But this timer tick event occurs in the class file
"PeriodicUpload.cs" and not on the form1.cs. I have also a try and catch
block
where i fire the event for the label. But I am doing something wrong en get
the warning message "Illegal Cross Thread Calls" in VS2005. I get this
because I have send the form1 object as a parameter to the constructor of
PeriodicUpload and this is not the approperiate way to do so in VS2005. What
i want to know is, how to do it with delegate and events.

I will add the source file here: look at "WebStatGen" in periodicUpload.cs
this not the appropriate way to do this in VS2005

Form1.cs source file:
----------------------------------------------------
using System;
using System.IO;
using FtpLib;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WinWebQ
{
public partial class WebStatGen : Form
{
public static string llabel;
PeriodicUpload periodicUpload = null;
public WebStatGen()
{
InitializeComponent();
FtpConfigManager fcm = new
FtpConfigManager(Application.StartupPath);
periodicUpload = new PeriodicUpload(fcm.create() ,
@"c:\yoyo\cms_stats\CSV_test.html", this);
}

private void button1_Click(object sender, EventArgs e)
{

}

private void label1_Click(object sender, EventArgs e)
{

}

private void btn_Start_Click(object sender, EventArgs e)
{
btn_Stop.Enabled = true;
btn_Start.Enabled = false;
periodicUpload.Start();

}

private void fTPConfigToolStripMenuItem_Click(object sender,
EventArgs e)
{
FTP_Options FTP_Form = new FTP_Options();
FTP_Form.ShowDialog(this);
FtpConfigManager ftpConfigFactory = new
FtpConfigManager(Application.StartupPath);
FTPConfig fc = ftpConfigFactory.create();
periodicUpload.changeCongifuration(fc);
}

private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
WebStatGen Gen_Form = new WebStatGen();
Application.Exit();
}
public void Statusss(int status)
{
if (status == 0)
{
this.label2.Text = "Status OK";
this.label2.ForeColor = System.Drawing.Color.Green;
}
else
{
this.label2.Text = "Status NOK";
this.label2.ForeColor = System.Drawing.Color.Red;
}
}
private void btn_Stop_Click(object sender, EventArgs e)
{
btn_Stop.Enabled = false;
btn_Start.Enabled = true;
periodicUpload.Stop();

}
}}

---------- End form1.cs --------------------------------

PeriodicUpload.cs
--------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Timers;
using FtpLib;

namespace WinWebQ
{
class PeriodicUpload
{
private static FTPFactory ff;
private Timer timer = null;
private static String fileToUpload = null;
private FTPConfig config;
private static WebStatGen gg; // object call

private static void TimerEventHandler( object source,
ElapsedEventArgs e )
{
readInputFile rif = new readInputFile();
rif.readfile();

try
{
gg.Statusss(1);
ff.upload(fileToUpload);
}
catch (Exception)
{
gg.Statusss(1);

ff.setRemoteHost("ftp.casblokker.nl");
ff.setRemoteUser("wicom");
ff.setRemotePass("12345");
ff.login();
ff.chdir("../WebQ");
ff.setBinaryMode(true);

ff.upload(fileToUpload);
}
}

public PeriodicUpload(FTPConfig _config, String _fileToUpload,
WebStatGen _gg)
{
config = _config;
gg = _gg;
fileToUpload = _fileToUpload;
InitFTP();
InitTimer();
}

public void changeCongifuration(FTPConfig _config)
{
config = _config;
timer.Interval = config.timeout;
}

private void InitTimer()
{
timer = new Timer();
timer.Elapsed += new ElapsedEventHandler(TimerEventHandler);
timer.Interval = config.timeout;
}

public void Start()
{
ff.setRemoteHost(config.hostname);
ff.setRemoteUser(config.username);
ff.setRemotePass(config.password);
ff.login();
ff.chdir(config.remotedir);
ff.setBinaryMode(true);
timer.Start();
timer.Enabled = true;
}

private static void InitFTP()
{
ff = new FTPFactory();
ff.setDebug(true);

}

public void Stop()
{
timer.Enabled = false;
ff.close();
}
}

}

------------- End PeriodicUpload.cs ---------------









- Zitierten Text anzeigen -

To get PeriodicUpload to fire a custom status event you would have to
declare a Delegate type for it somewhere (I normally put these outside
of the actual classes, in the namespace):

public delegate void StatusChangedEventHandler (object sender,
StatusChangedEventArgs e);

This also requires that you create a StatusChangedEventArgs-class that
holds the relevant information for this event. You could also just
have an int here, but with its own class it is easier to return more
information if something changes later on.
Then you would declare the event inside the PeriodicUpload class like
this:

public event StatusChangedEventHandler StatusChanged;

After that you could raise the event from inside of PeriodicUpdate
like this:

if (StatusChanged != null)
{
StatusChanged(this, new StatusChangedEventArgs(1));
}

The nullity check is required to make sure that someone is actually
subscribed to your event and there is a delegate instance to invoke.
If you use .Net 2.0 you could also assign a default delegate instance
when declaring the event like this:

public event StatusChangedEventHandler StatusChanged = delegate
(object sender, StatusChangedEventArgs e) { };

This should cover the basics of implementing your own events, however,
I am not quite sure that this will help in your case. As far as I can
see this code should work (although passing a reference to the form in
the constructor is not elegant). Since you get the "Illegal Cross
Thread Calls" exception, one would assume that there is some form of
multi-threading going on, since it is in fact not allowed to alter the
GUI (i.e. changing the text of your label) from a different thread
in .Net 2.0. In .Net 1.1 it was possible, but still a bad idea (which
is why it is illegal altogether now).

hth,
Kevin Wienhold
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top