Samuel Folkner Samuel Folkner - 2 months ago 8
C# Question

How to use delegate and event?

I'm trying to learn C# and programming in general and I have encountered a problem. I have tried to search for answers but failed, so I'm sorry if I'm duplicating another topic.

I have 1 windows form (Form1), external class (Class1), button and label on Form.
This class is a simple file shredder, that starts on button click. Label1.text should be updated from the external class, showing what file is being shredded right now.

I have found out, that I need to use delegates and events to make that happen correctly, but I don't know how to use them right.
Code here:

//Form1
private async void button2_Click(object sender, EventArgs e)
{
var task = new Task(() =>
{
check = true;
bool success = FileUtilities.Shred(textBox1.Text);
});
task.Start();
public void ChangeName(string text)
{
label3.Text = text;
}

//Class1
public static bool ShredFile(string filePath, bool shouldDelete = true)
{
bool success = true;
try
{
FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Write);
//Label1.text = filePath; - should be like that.


I have tried to use
public void ChangeName
to access the property, but it didn't work. I can't understand where should I create a delegate, an event and where to subscribe to this event.

UPDATE: I have found out what was the problem. I had several threads in my program and I couldn't access label on form through my class. I had to use callback and after that subscription and event worked perfectly. Thank you, Thorsten Dittmar, for showing the right way.

Answer

There are actually a few ways to achieve what you want. I'd go the following way, beacuse it is easiest to implement and does not involve any callbacks ;-)

The basic throught behind this is: Leave UI updates to classes that maintain the UI. Everything else is a tool and doesn't even need to know whether there's an UI or not.

If you have a point in your UI code where shredding a file is triggered, perform three steps:

  1. Update your UI, for example show the file name of the file being shredded (UI class)
  2. Shred the file (tool class)
  3. Show success or failure of the shredding operation (UI class)

See? No events :-)

But your question was how to actually create and use events, so....

Generally an event consists of two parts on the sender side:

  • an event
  • a method to raise the event

You declare both of them like this, for example.

public class EventSender
{
    public event EventHandler<EventArgsType> MyEvent;

    protected void OnMyEvent(...)
    {
        if (MyEvent != null)
            MyEvent(this, new EventArgsType(...));
    }
}

The EventArgsType is a subclass of EventArgs which you can use to pass information from the sender to the receiver. An example:

public class EventSender
{
    public class EventArgsType : EventArgs
    {
        public EventArgsType(string fileName) : base()
        {
            FileName = fileName;
        }

        public string FileName
        {
            get;
            private set;
        }
    }

    public event EventHandler<EventArgsType> MyEvent;

    protected void OnMyEvent(string filename)
    {
        if (MyEvent != null)
            MyEvent(this, new EventArgsType(filename));
    }
}

Whenever the event should be raised, it is enough to call the OnMyEvent method from within the EventSender class.

Now the receiver needs to attach itself to the event and then a method will be called whenever the event is fired. Example

public class Receiver
{
    private EventSender _sender;

    public Receiver()
    {
        _sender = new EventSender();
        _sender.MyEvent += HandleMyEvent;
    }

    private void HandleMyEvent(object sender, EventSender.EventArgsType e)
    {
        // Do something with e.FileName
    }
}

So what would I do in your case? I'd create a nonstatic class FileShredder that implements one or more events similar to by example and has a nonstatic method to shred a file.

Before starting any task in your UI, I'd create an instance of this class, attach the required event handlers and then I'd use that instance to shred the files. In the event handlers in your UI class, change the labels and stuff.

Comments