Event handling

  • Thread starter Thread starter David
  • Start date Start date
D

David

Hi all,

I am currently writing an app for a mobile phone. (WM6) with Compact
Framework, though this probably has no bearing on my question.

I am building the app as a layered app. I have my main screen, but behind
this, I have for example, a class that talks to the bluetooth device.

So, for example...

Form1.cs

Here I have...

Bluetooth bt = new Bluetooth();
bt.Connect(); // Asks the bluetooth connection to start and be ready to
handle incoming files.


classes\Bluetooth.cs

public void Connect()
{
// Do my bluetooth actions.
// This also starts a thread.
}

private void BTThreadHandler()
{
// This is the thread handler that was started in connect.
// This saves a file.
}

What I need to do is to allow the BTThreadHandler to notify Form1.cs when a
file has arrived. I actually need to pass the filename. I could store the
filename in a property but if another file comes in, the property will no
doubt change, so a property is not really safe in this instance.


For the event handler, in the past, I have done something like this, but I
don't know if this would be normal... is it?

Form1.cs
bt.EventUpdateData += new EventHandler(CollectDataHandler);

private void CollectDataHandler(object sender, EventArgs e)
{
// handle the event
}


classes\Bluetooth.cs

public event EventHandler EventUpdateData;

private void BTThreadHandler()
{
// This is the thread handler that was started in connect.
// This saves a file.

// Create an event
if (EventUpdateData != null)
EventUpdateData(sender, e); // Note, this is copied, so
sender and e are not valid here.
}


Is this how it is done?

I guess that to pass the filename string, instead of using sender and e, I
just send the string.


Your advice is appreciated. If the above is the wrong way, I would
appreciate the details of how it should be done.

--
Best regards,
Dave Colliver.
http://www.AshfieldFOCUS.com
~~
http://www.FOCUSPortals.com - Local franchises available
 
I think the step you're missing is that you can create your own EventArgs
and add any data you want.

Then you can define your own delegate


public delegate void SomethingHappenedWithARootFolder (object sender,
RootFolderEventArgs arg);




public class RootFolderEventArgs : System.EventArgs
{
private Guid _rootFolderUUID = Guid.Employ;
private string _folderPath = string.Empty;
public string FolderPath
{
get
{
return _folderPath;
}
set
{
_folderPath = value;
}
}

public Guid RootFolderUUID
{
get
{
return _rootFolderUUID;
}
set
{
_rootFolderUUID = value;
}
}

}


======================================
Then on some class, you expose the event


public MyClass
{


public event SomethingHappenedWithARootFolder
SomethingHappenedWithARootFolderEvent;


private void OnRootFolderEventArgs (object sender, RootFolderEventArgs arg)

{

if (null != SomethingHappenedWithARootFolderEvent)

{

SomethingHappenedWithARootFolderEvent(sender, arg);

}

}



public void SomeNormalCode()

{

RootFolderEventArgs args = new RootFolderEventArgs ();

args.RootFolderUUID= Guid.Empty;

args.FolderPath= "c:\wutemp\";

OnRootFolderEventArgs (this, args );



}


}



This may not be the latest/greatest SYNTAX or usage, but it'll get you
going.






The
 
Thanks, so in my own example, it is the bluetooth.cs that needs to raise the
event... and it is the form1.cs that needs to handle it.

Where would the delegate go?

your MyClass I am assuming is the same as my form1.cs

I am also assuming that your SomeNormalCode() is what should be in my
bluetooth.cs

--
Best regards,
Dave Colliver.
http://www.AshfieldFOCUS.com
~~
http://www.FOCUSPortals.com - Local franchises available
 
// private void OnRootFolderEventArgs(RootFolderEventArgs arg)//
Good point, I (now) see the unneeded (double use of ~this~) in my code.
Aka, the above method doesn't need the first argument of sender.


//> EventHandler said:
SomethingHappenedWithARootFolderEvent;//
//Actually, you don't need to declare a delegate type anymore.//

Correct. This was some leftover 1.1 code that got upconverted to 2.0 (in my
original).

.......

I think the guy is on the right path now.
 
Cool...

I was just coming back to the group after I had tried to implement it (and
failed).

In my form1.cs I have...

bt.FileReceivedEvent += new EventHandler(BTFileReceived);

which points to...

protected void BTFileReceived(object sender, FileReceivedEventArgs e)

{

ReturnPicture.Image = new Bitmap(wsc.SendFile());

}

however, I got a
No overload for 'BTFileReceived' matches delegate 'System.EventHandler'

So, I will try with the extended example posted here.

Thanks for the help and especially showing me the difference between a
single threaded version and a multithreaded version. As the event is being
raised in a thread, it is of particular importance, which is the main reason
I asked. :-)
--
Best regards,
Dave Colliver.
http://www.AshfieldFOCUS.com
~~
http://www.FOCUSPortals.com - Local franchises available
 
I think your class ( doing the event raising ) needs something like


public event EventHandler<FileReceivedEventArgs > FileReceivedEvent ;



Or do you have it that already?
 
Getting a LOT closer now, thanks for your help so far...

I have just changed my code with this, now my code in my bluetooth file
looks like...

public class FileReceivedEventArgs : System.EventArgs
{
private string _FileName = string.Empty;
public string FileName
{
get { return _FileName; }
set { _FileName = value; }
}
}

class Bluetooth
{
public event EventHandler<FileReceivedEventArgs> FileReceivedEvent;

private btFile()
{
string filename = "test.txt";

// Raise event...
FileReceivedEventArgs args = new FileReceivedEventArgs();
args.FileName = filename;

OnFileReceivedEventArgs(args);
}

private void OnFileReceivedEventArgs(FileReceivedEventArgs args)
{
EventHandler<FileReceivedEventArgs> handler = FileReceived;
if (handler != null)
{
handler(this, args);
}
}
}


but I am still getting an error on my form1 in the same place...

bt.FileReceivedEvent += new EventHandler(BTFileReceived);

(The above line is in my form_load).

The BTFileReceived now looks like...
protected void BTFileReceived(object sender, FileReceivedEventArgs
e)
{
ReturnPicture.Image = new Bitmap(wsc.SendFile());
}



Finally, as this is working via a thread, I am currently declaring wsc at
the class level rather than inside the BTFileReceived. I have just moved my
wsc declaration into the BTFileReceived. Is this required for thread safety?
I am guessing it is, as BTFileReceived will create an instance of the wsc
class for its own use.


--
Best regards,
Dave Colliver.
http://www.AshfieldFOCUS.com
~~
http://www.FOCUSPortals.com - Local franchises available
 
Magic...

That all builds now.

I have renamed FileReceivedEvent to FileReceived as well.

Thanks for your help guys.

--
Best regards,
Dave Colliver.
http://www.AshfieldFOCUS.com
~~
http://www.FOCUSPortals.com - Local franchises available


Peter Duniho said:
Cool...

I was just coming back to the group after I had tried to implement it
(and
failed).

In my form1.cs I have...

bt.FileReceivedEvent += new EventHandler(BTFileReceived);

[...]

In addition to sloan's comment suggesting something you should
double-check, the above can be changed to:

bt.FileReceivedEvent += BTFileReceived;

This does two things. First, it avoids the incorrect construction of an
EventHandler instance. Even if you have the event type correct, you can't
make an EventHandler delegate from a method that doesn't have Object or
EventHandler as the second argument.

The second thing it does is use the newer inferred delegate syntax, where
the compiler looks at the destination type and automatically creates a
delegate of the correct type for you. You could fix the line by changing
"EventHandler" to "EventHandler<FileReceivedEventArgs>", but the newer
syntax is a lot nicer IMHO.

Once you've ensured that the event is declared correctly and changed the
above line, it should compile.

Finally, I'll point out that the .NET convention is for event names to not
include the word "Event" at the end. It's not mandatory by any means, but
following the .NET convention, your event would be named "FileReceived"
instead.

Pete
 
Back
Top