473,396 Members | 2,011 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Event or other?

Hi All,

I'm a newbee in C# and have a Windows form application. The main form
has a progress bar. In one of the methods of the main form, I call a
class derived from Object which processes a file. During the
processing, I'd like the custom class to be able to update the
progress bar.

What's the best way to make this happen? I've been reading up on
events/delegates and am beginning to get a vague understanding, but I
wanted to make sure I'm not going down the wrong path.

Thanks for any suggestions/insight,
Steve
Sep 13 '07 #1
12 1356
Hi,

"Steve" <ki****@harpservices.comwrote in message
news:iv********************************@4ax.com...
Hi All,

I'm a newbee in C# and have a Windows form application. The main form
has a progress bar. In one of the methods of the main form, I call a
class derived from Object which processes a file. During the
processing, I'd like the custom class to be able to update the
progress bar.

What's the best way to make this happen? I've been reading up on
events/delegates and am beginning to get a vague understanding, but I
wanted to make sure I'm not going down the wrong path.
You have to use a thread to perform the operation and in the meantime in the
UI thread the progress bar is running.
Take a look at Control.Invoke as the way to communication between the worker
thread and the UI
Sep 13 '07 #2
On Thu, 13 Sep 2007 21:36:25 +0200, Steve <ki****@harpservices.comwrote:
Hi All,

I'm a newbee in C# and have a Windows form application. The main form
has a progress bar. In one of the methods of the main form, I call a
class derived from Object which processes a file. During the
processing, I'd like the custom class to be able to update the
progress bar.

What's the best way to make this happen? I've been reading up on
events/delegates and am beginning to get a vague understanding, but I
wanted to make sure I'm not going down the wrong path.

Thanks for any suggestions/insight,
Steve
Hi Steve

An event should work fine here, but you also need to start your processing in a BackgroundWorker or another thread or the main thread won't get time to process the event. And since the event will get caught in a thread other than the main thread, you need to use Invoke as well. The sample below might give you some ideas. If you don't mind having the classcall the form directly (which isn't really good OO practice, you can skip throwing the event and call the form directly)

public class MyForm : Form
{

<...>

delegate void ProgressBarDelegate(int value);
BackgroundWorker worker = new BackgroundWorker();
MyClass myClass = new MyClass();

private void Method()
{
myClass.MyEvent += new MyClass.MyEventHandler(myClass_MyEvent);
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCom pleted);
worker.RunWorkerAsync();
}

void myClass_MyEvent(int value)
{
if (progressBar1.InvokeRequired)
progressBar1.Invoke(new ProgressBarDelegate(myClass_MyEvent), new object[] { value });
else
progressBar1.Value = value / 2;
}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
myClass.Method();
}

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Done");
}
}

public class MyClass
{
public event MyEventHandler MyEvent;
public delegate void MyEventHandler(int value);

public void Method()
{
for (int i = 0; i < 200; i++)
{
System.Threading.Thread.Sleep(200);
MyEvent(i);
}
}
}

--
Happy coding!
Morten Wennevik [C# MVP]
Sep 13 '07 #3
On Thu, 13 Sep 2007 16:05:20 -0400, "Ignacio Machin \( .NET/ C# MVP
\)" <machin TA laceupsolutions.comwrote:
>Hi,

"Steve" <ki****@harpservices.comwrote in message
news:iv********************************@4ax.com.. .
>Hi All,

I'm a newbee in C# and have a Windows form application. The main form
has a progress bar. In one of the methods of the main form, I call a
class derived from Object which processes a file. During the
processing, I'd like the custom class to be able to update the
progress bar.

What's the best way to make this happen? I've been reading up on
events/delegates and am beginning to get a vague understanding, but I
wanted to make sure I'm not going down the wrong path.

You have to use a thread to perform the operation and in the meantime in the
UI thread the progress bar is running.
Take a look at Control.Invoke as the way to communication between the worker
thread and the UI
I'd like to avoid multi-threading if I can. I have no experience in
managing threads and it doesn't seem like it should be that
complicated to just reference a component on a form.
Sep 13 '07 #4
Hi,

"Steve" <ki****@harpservices.comwrote in message
news:mb********************************@4ax.com...
On Thu, 13 Sep 2007 16:05:20 -0400, "Ignacio Machin \( .NET/ C# MVP
\)" <machin TA laceupsolutions.comwrote:
>>Hi,

"Steve" <ki****@harpservices.comwrote in message
news:iv********************************@4ax.com. ..
>>Hi All,

I'm a newbee in C# and have a Windows form application. The main form
has a progress bar. In one of the methods of the main form, I call a
class derived from Object which processes a file. During the
processing, I'd like the custom class to be able to update the
progress bar.

What's the best way to make this happen? I've been reading up on
events/delegates and am beginning to get a vague understanding, but I
wanted to make sure I'm not going down the wrong path.

You have to use a thread to perform the operation and in the meantime in
the
UI thread the progress bar is running.
Take a look at Control.Invoke as the way to communication between the
worker
thread and the UI
I'd like to avoid multi-threading if I can. I have no experience in
managing threads and it doesn't seem like it should be that
complicated to just reference a component on a form.

It's not complicated, besides if you never start you will never learn :)

See the other post in this thread as well as in the archives, a solution to
your problem is posted or discussed at least once a week
Sep 13 '07 #5


"Morten Wennevik [C# MVP]" wrote:
On Thu, 13 Sep 2007 21:36:25 +0200, Steve <ki****@harpservices.comwrote:
Hi All,

I'm a newbee in C# and have a Windows form application. The main form
has a progress bar. In one of the methods of the main form, I call a
class derived from Object which processes a file. During the
processing, I'd like the custom class to be able to update the
progress bar.

What's the best way to make this happen? I've been reading up on
events/delegates and am beginning to get a vague understanding, but I
wanted to make sure I'm not going down the wrong path.

Thanks for any suggestions/insight,
Steve

Hi Steve

An event should work fine here, but you also need to start your processing in a BackgroundWorker or another thread or the main thread won't get time to process the event. And since the event will get caught in a thread other than the main thread, you need to use Invoke as well. The sample below might give you some ideas. If you don't mind having the class call the form directly (which isn't really good OO practice, you can skip throwing the event and call the form directly)

public class MyForm : Form
{

<...>

delegate void ProgressBarDelegate(int value);
BackgroundWorker worker = new BackgroundWorker();
MyClass myClass = new MyClass();

private void Method()
{
myClass.MyEvent += new MyClass.MyEventHandler(myClass_MyEvent);
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCom pleted);
worker.RunWorkerAsync();
}

void myClass_MyEvent(int value)
{
if (progressBar1.InvokeRequired)
progressBar1.Invoke(new ProgressBarDelegate(myClass_MyEvent), new object[] { value });
else
progressBar1.Value = value / 2;
}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
myClass.Method();
}

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Done");
}
}

public class MyClass
{
public event MyEventHandler MyEvent;
public delegate void MyEventHandler(int value);

public void Method()
{
for (int i = 0; i < 200; i++)
{
System.Threading.Thread.Sleep(200);
MyEvent(i);
}
}
}

--
Happy coding!
Morten Wennevik [C# MVP]
Hi Morten,

Thanks for the reply very useful. The only problem I get whilst running that
code is when I get to the MyEvent(i); call in public void Method() I get a
NullReferenceException with "Object reference not set to an instance of an
object". Any idea what I'm doing wrong?

Cheers,

Andy
Oct 17 '07 #6
That means that nobody is listening to your event; a minor nuicance,
but you need to check events for null; this is usually done in an "On"
method, i.e. (given your unusual event signature):

protected virtual void OnMyEvent(int value) {
MyEventHandler handler = MyEvent;
if(handler!=null) handler(value);
}

and then call OnMyEvent(i); instead of MyEvent(i);

For a lazy implementation, you could just use:
if(MyEvent!=null) {MyEvent(i);}
but there are a few subtle issues that make the OnMyEvent the
recommended approach.

Marc
Oct 17 '07 #7

"Marc Gravell" wrote:
That means that nobody is listening to your event; a minor nuicance,
but you need to check events for null; this is usually done in an "On"
method, i.e. (given your unusual event signature):

protected virtual void OnMyEvent(int value) {
MyEventHandler handler = MyEvent;
if(handler!=null) handler(value);
}

and then call OnMyEvent(i); instead of MyEvent(i);

For a lazy implementation, you could just use:
if(MyEvent!=null) {MyEvent(i);}
but there are a few subtle issues that make the OnMyEvent the
recommended approach.

Marc
Hi Marc,

Thanks for the reply - I'm obviously not doing something right;

In my form I have:-

delegate void ProgressBarDelegate(int value);
BackgroundWorker worker = new BackgroundWorker();

TryClass myClass = new TryClass();
private void Method()
{
myClass.MyEvent += new TryClass.MyEventHandler(myClass_MyEvent);
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(worker_RunWorkerCom pleted);
worker.RunWorkerAsync();
}

void myClass_MyEvent(int value)
{
if (prgStatus.InvokeRequired)
prgStatus.Invoke(new ProgressBarDelegate(myClass_MyEvent),
new object[] { value });
else
prgStatus.Value = value / 2;
}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
myClass.Method();
}

void worker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Done");
}

In the class I have :-

public event MyEventHandler MyEvent;
public delegate void MyEventHandler(int value);

public void Method()
{
for (int i = 0; i < 100; i++)
{
System.Threading.Thread.Sleep(200);

if (MyEvent != null)
{ MyEvent(i); }

}
}

I am then calling the method from another class in the same project;

TryClass x = new TryClass ();
x.Method();

All I seem to get are null values in the MyEvent(i) - any ideas what I am
doing wrong? It's like the MyEvent doesn't connect back to the form.

Thanks,

Andy
Oct 17 '07 #8
All I seem to get are null values in the MyEvent(i)
Sorry - can you clarify what you mean? is MyEvent null? Or is
something throwing an exception?

Note that with BackgroundWorker, a better way to handle the updates is
to set WorkerReportsProgress = true, and then from your loop call
ReportProgress(value). You can then catch the ProgressChanged event
(which is fired on the UI thread, so no InvokeRequired / Invoke) and
get the value from the event-arg.

Marc
Oct 17 '07 #9
Andy C wrote:
Thanks for the reply - I'm obviously not doing something right;
Correct. :)
In my form I have:-

delegate void ProgressBarDelegate(int value);
BackgroundWorker worker = new BackgroundWorker();

TryClass myClass = new TryClass();
So, in your form, you've created an instance of TryClass() and subscribe
your event handler to the event in that instance.
[...]
I am then calling the method from another class in the same project;

TryClass x = new TryClass ();
And then within your background worker thread, you create a new instance
of TryClass().
x.Method();
And then call the method that raises the event using that new instance,
rather than the instance in which you subscribed your handler.
All I seem to get are null values in the MyEvent(i) - any ideas what I am
doing wrong? It's like the MyEvent doesn't connect back to the form.
You are creating a new instance of TryClass. That instance is not the
same one to which you subscribed your event handler, so of course the
event in that instance isn't subscribed.

You need to create just one instance of the class, and then use that
instance when executing the method of interest. Alternatively (and this
comes up more often than one might think) if you can genuinely get away
with creating a new instance each time you want to call the method, then
that method shouldn't be an instance method anyway as you're obviously
not using anything that is unique per-instance.

In this alternative case, just make the method and the event static.
And of course, if you have no other instance members in the class, then
the class itself could be static.

Pete
Oct 17 '07 #10


"Peter Duniho" wrote:
Andy C wrote:
Thanks for the reply - I'm obviously not doing something right;

Correct. :)
In my form I have:-

delegate void ProgressBarDelegate(int value);
BackgroundWorker worker = new BackgroundWorker();

TryClass myClass = new TryClass();

So, in your form, you've created an instance of TryClass() and subscribe
your event handler to the event in that instance.
[...]
I am then calling the method from another class in the same project;

TryClass x = new TryClass ();

And then within your background worker thread, you create a new instance
of TryClass().
x.Method();

And then call the method that raises the event using that new instance,
rather than the instance in which you subscribed your handler.
All I seem to get are null values in the MyEvent(i) - any ideas what I am
doing wrong? It's like the MyEvent doesn't connect back to the form.

You are creating a new instance of TryClass. That instance is not the
same one to which you subscribed your event handler, so of course the
event in that instance isn't subscribed.

You need to create just one instance of the class, and then use that
instance when executing the method of interest. Alternatively (and this
comes up more often than one might think) if you can genuinely get away
with creating a new instance each time you want to call the method, then
that method shouldn't be an instance method anyway as you're obviously
not using anything that is unique per-instance.

In this alternative case, just make the method and the event static.
And of course, if you have no other instance members in the class, then
the class itself could be static.

Pete
Hi Peter,

Thanks for the reply - I think I'm nearly there now. I made the class static
but I'm still getting nothing but null values.

In the class I have;

public static class TryClass
{
public static event MyEventHandler MyEvent;

public delegate void MyEventHandler(int value);

public static void Method()
{
for (int i = 0; i < 100; i++)
{
System.Threading.Thread.Sleep(200);

if (MyEvent != null)
{ MyEvent(i); }

}
}

In the form I have;

delegate void ProgressBarDelegate(int value);
BackgroundWorker worker = new BackgroundWorker();

private void Method()
{
TryClass.MyEvent += new TryClass.MyEventHandler(TryClass_MyEvent);
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(worker_RunWorkerCom pleted);
worker.RunWorkerAsync();
}

void TryClass_MyEvent(int value)
{
if (prgStatus.InvokeRequired)
prgStatus.Invoke(new ProgressBarDelegate(TryClass_MyEvent),
new object[] { value });
else
prgStatus.Value = value / 2;
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
TryClass.Method();
}

void worker_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Done");
}

I'm now calling TryClass.Method(); and I'm still getting nothing but null
values.

Thanks,

Andrew
Oct 18 '07 #11
Andy C wrote:
[...]
I'm now calling TryClass.Method(); and I'm still getting nothing but null
values.
Well, maybe I'm just overlooking something, but I didn't see anything
obviously wrong in the code you posted (other than the fact that you
don't unsubscribe from the event after you're done with it, but that
won't affect whether you can be called when the event is raised).

If no one else catches the error, you should post a concise-but-complete
example of code that demonstrates the problem. Assuming I didn't miss
anything, the fact that it's still not working means that there's
something in the code you didn't post that's causing a problem.

Having a concise-but-complete code example would allow anyone to just
compile the thing and test it themselves. Since there's nothing about
what you're trying to do that requires a form, the code you post should
actually be a console application. Yes, this means you need to
basically write a new code sample, copying the important bits from the
code that already exists.

Of course, that assumes the code you posted is exactly the code you're
using. If it's not strictly a copy-and-paste from your program, that's
obviously going to prevent anyone from saying what's wrong with the code
you're actually using. :)

Pete
Oct 18 '07 #12
Many thanks - I got it to work. It helps if you actually call the event in
the first place. Doh!
Oct 19 '07 #13

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Andy Read | last post by:
Hello all, I have the requirement to produce source code that produces an object hierarchy. Example: Root | Folder 1
18
by: Christopher W. Douglas | last post by:
I am writing a VB.NET application in Visual Studio 2003. I have written a method that handles several events, such as closing a form and changing the visible status of a form. I have some code...
3
by: boxboy | last post by:
I am hoping someone from Microsoft could shed some insight into this question. Why did microsoft decide to use a verb based naming convtion for events rather such as Close and Click for rather...
5
by: Maxine G | last post by:
I have two forms, a menu and a data entry form. The entry form is bound to a query against linked SQL server tables. In the deactivate event, I have some code which asks the user if they want to...
3
by: Edward Diener | last post by:
According to the CLS specification, the accessibility of the methods for adding, removing, and raising an event must be identical. There appear to be a few problems with this: 1) According to...
7
by: Charles Law | last post by:
I may have asked this before, but what is the purpose of both these functions? Is there a time when one should be called over the other? Does one supersede the other, or do they both have their...
12
by: Jack Russell | last post by:
My unstanding of all VB up to and including vb6 is that an event could not "interrupt" itself. For instance if you had a timer event containing a msgbox then you would only get one message. ...
8
by: Pete | last post by:
Assume I have an n by n matrix of identical objects, each of which can both invoke and consume event A. If, say, obect invokes the event, the only other objects that need to consume it are those in...
19
by: Daniela Roman | last post by:
Hello, I try to fire an event under a button click event and maybe anybody can give a clue please. I have let's say a WEB grid with PageIndexChanged event: private void...
5
by: jaysonnward | last post by:
Hello All: I've recently been recreating some 'dropdown menus' for a website I manage. I'm writing all my event handlers into my .js file. I've got the coding to work in Firefox, but the...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.