473,382 Members | 1,332 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,382 software developers and data experts.

Can you raise an event that doesn't block?

I understand that you would normally want to raise an event on the same
thread so that your code blocks until the event has been dealt with...
however i've run into a situation where I have a thread running that
isn't my form thread and I want it to raise a custom event and continue
going without waiting for that event to be handled...

Is this at all possible?
Nov 23 '05 #1
12 2884
Benny,

Sure. Just use the BeginInvoke method on the event, which will spawn off a
thread pool thread to service this call, and your thread will go on its
marry way. Just remember that if there are more than one items in the
invocation list inside of the event (see GetInvocationList of the event)
that you have to iterate through them all and call BeginInvoke on each.

Dave

"Benny Raymond" <be***@pocketrocks.com> wrote in message
news:%2****************@tk2msftngp13.phx.gbl...
I understand that you would normally want to raise an event on the same
thread so that your code blocks until the event has been dealt with...
however i've run into a situation where I have a thread running that isn't
my form thread and I want it to raise a custom event and continue going
without waiting for that event to be handled...

Is this at all possible?

Nov 23 '05 #2
It seems to be working - but since I don't understand it that much I'd
like for you to look at the code and let me know I did it right... thanks!

// My event thing
#region Delegates and Event Declarations > MessageReceived Event
public delegate void MessageReceivedEventHandler( ServerMessage sMsg );
public event MessageReceivedEventHandler MessageReceived;
private void OnMessageReceived( ServerMessage sMsg )
{
if ( MessageReceived != null )
{
IEnumerator myEnum = MessageReceived.GetInvocationList().GetEnumerator( );
while ( myEnum.MoveNext() )
{
( (MessageReceivedEventHandler) myEnum.Current ).BeginInvoke(sMsg, null,
null);
}
}
}
#endregion

// Inside the thread that loops round and round,
// if a message is recieved in this loop, it runs this line:
OnMessageReceived( message );


D. Yates wrote:
Benny,

Sure. Just use the BeginInvoke method on the event, which will spawn off a
thread pool thread to service this call, and your thread will go on its
marry way. Just remember that if there are more than one items in the
invocation list inside of the event (see GetInvocationList of the event)
that you have to iterate through them all and call BeginInvoke on each.

Dave

"Benny Raymond" <be***@pocketrocks.com> wrote in message
news:%2****************@tk2msftngp13.phx.gbl...
I understand that you would normally want to raise an event on the same
thread so that your code blocks until the event has been dealt with...
however i've run into a situation where I have a thread running that isn't
my form thread and I want it to raise a custom event and continue going
without waiting for that event to be handled...

Is this at all possible?


Nov 23 '05 #3
>Just remember that if there are more than one items in the
invocation list inside of the event (see GetInvocationList of the event)
that you have to iterate through them all and call BeginInvoke on each.

I think you don't need that unless you want _each_ registered handler
to be run on its own thread. Normally, calling BeginInvoke on the event
is adequate, and all the registered handlers will be invoked
sequecially on a same separate thread.

Thi

Nov 23 '05 #4
Sequencially is fine... but now i run into another problem...

inside of the function that gets fired in the main form when the said
event takes place, I have the following line:
if (this.txt_log.Text.Length > 1024*60)

it's checking to see if the text in a rich text box is larger than 60k.
After the event is fired a bunch of times really fast, the program
crashes here and returns just after the
System.Windows.Forms.Application.Run(new frmMain());
inside Main saying that an Object Refrence not set to an instance of an
object... I had to step through my code to find out where it was
crashing... and when I mouse over .Length while stepping through Visual
Studio freezes up for a good 10 seconds and then displays no information
about .Length

Any idea what would be causing this?

Truong Hong Thi wrote:
Just remember that if there are more than one items in the
invocation list inside of the event (see GetInvocationList of the event)
that you have to iterate through them all and call BeginInvoke on each.


I think you don't need that unless you want _each_ registered handler
to be run on its own thread. Normally, calling BeginInvoke on the event
is adequate, and all the registered handlers will be invoked
sequecially on a same separate thread.

Thi

Nov 23 '05 #5
Here's the full stack trace:

Unhandled Exception: System.NullReferenceException: Object reference not
set to an instance of an object.
at System.Windows.Forms.RichTextBox.EditStreamProc(In tPtr dwCookie,
IntPtr buf, Int32 cb, Int32& transferred)
at System.Windows.Forms.UnsafeNativeMethods.CallWindo wProc(IntPtr
wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.NativeWindow.DefWndProc(Messa ge& m)
at System.Windows.Forms.Control.DefWndProc(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.TextBoxBase.WndProc(Message& m)
at System.Windows.Forms.RichTextBox.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage (Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(M essage& m)
at System.Windows.Forms.NativeWindow.DebuggableCallba ck(IntPtr hWnd,
Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.PeekMessa ge(MSG& msg,
HandleRef hwnd, Int32 msgMin, Int32 msgMax, Int32 remove)
at SystThe program '[3208] TKSAdmin.exe' has exited with code 0 (0x0).
em.Windows.Forms.ComponentManager.System.Windows.F orms.UnsafeNativeMethods+IMsoComponentManager.FPus hMessageLoop(Int32
dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.ThreadContext.RunMessageLoopI nner(Int32
reason, ApplicationContext context)
at System.Windows.Forms.ThreadContext.RunMessageLoop( Int32 reason,
ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at TKSAdmin.Globals.Main()

Benny Raymond wrote:
Sequencially is fine... but now i run into another problem...

inside of the function that gets fired in the main form when the said
event takes place, I have the following line:
if (this.txt_log.Text.Length > 1024*60)

it's checking to see if the text in a rich text box is larger than 60k.
After the event is fired a bunch of times really fast, the program
crashes here and returns just after the
System.Windows.Forms.Application.Run(new frmMain());
inside Main saying that an Object Refrence not set to an instance of an
object... I had to step through my code to find out where it was
crashing... and when I mouse over .Length while stepping through Visual
Studio freezes up for a good 10 seconds and then displays no information
about .Length

Any idea what would be causing this?

Truong Hong Thi wrote:
Just remember that if there are more than one items in the
invocation list inside of the event (see GetInvocationList of the event)
that you have to iterate through them all and call BeginInvoke on each.

I think you don't need that unless you want _each_ registered handler
to be run on its own thread. Normally, calling BeginInvoke on the event
is adequate, and all the registered handlers will be invoked
sequecially on a same separate thread.

Thi

Nov 23 '05 #6
Looks like it has something to do with modifying the text box in more
than one thread... i put this at the top which stoped the crash except
for when I click in the box while a line up updates is waiting to
happen.... am i doomed?:

private bool processMessage = false;
private void _client_MessageReceived(TaskulonServerCom.ServerMe ssage sMsg)
{
while (processMessage)
{
System.Threading.Thread.Sleep(1);
}
processMessage = true;
// bunch of code to do stuff with the text box
processMessage = false;
}

Benny Raymond wrote:
Here's the full stack trace:

Unhandled Exception: System.NullReferenceException: Object reference not
set to an instance of an object.
at System.Windows.Forms.RichTextBox.EditStreamProc(In tPtr dwCookie,
IntPtr buf, Int32 cb, Int32& transferred)
at System.Windows.Forms.UnsafeNativeMethods.CallWindo wProc(IntPtr
wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.NativeWindow.DefWndProc(Messa ge& m)
at System.Windows.Forms.Control.DefWndProc(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.TextBoxBase.WndProc(Message& m)
at System.Windows.Forms.RichTextBox.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage (Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(M essage& m)
at System.Windows.Forms.NativeWindow.DebuggableCallba ck(IntPtr hWnd,
Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.PeekMessa ge(MSG& msg,
HandleRef hwnd, Int32 msgMin, Int32 msgMax, Int32 remove)
at SystThe program '[3208] TKSAdmin.exe' has exited with code 0 (0x0).
em.Windows.Forms.ComponentManager.System.Windows.F orms.UnsafeNativeMethods+IMsoComponentManager.FPus hMessageLoop(Int32
dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.ThreadContext.RunMessageLoopI nner(Int32
reason, ApplicationContext context)
at System.Windows.Forms.ThreadContext.RunMessageLoop( Int32 reason,
ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at TKSAdmin.Globals.Main()

Benny Raymond wrote:
Sequencially is fine... but now i run into another problem...

inside of the function that gets fired in the main form when the said
event takes place, I have the following line:
if (this.txt_log.Text.Length > 1024*60)

it's checking to see if the text in a rich text box is larger than
60k. After the event is fired a bunch of times really fast, the
program crashes here and returns just after the
System.Windows.Forms.Application.Run(new frmMain());
inside Main saying that an Object Refrence not set to an instance of
an object... I had to step through my code to find out where it was
crashing... and when I mouse over .Length while stepping through
Visual Studio freezes up for a good 10 seconds and then displays no
information about .Length

Any idea what would be causing this?

Truong Hong Thi wrote:
Just remember that if there are more than one items in the
invocation list inside of the event (see GetInvocationList of the
event)
that you have to iterate through them all and call BeginInvoke on each.

I think you don't need that unless you want _each_ registered handler
to be run on its own thread. Normally, calling BeginInvoke on the event
is adequate, and all the registered handlers will be invoked
sequecially on a same separate thread.

Thi

Nov 23 '05 #7
>Looks like it has something to do with modifying the text box in more
than one thread

Yes, might be so. When you update Windows Form UI from other thread,
you need to use Control.Invoke or Control.BeginInvoke to marshall the
call to the thread that created the control. That limitation is due to
STA model of windows system.
I post a sample, note that I did not test it yet, just want to give the
idea.
private int GetTextLength(Control ctrl)
{
if (!ctrl.InvokedRequired)
{
return ctrl.Text.Length;
}
else
{
return (int) ctrl.Invoke(new TextLengthDelegate(GetTextLength),
new object[] {ctrl});
}
}

Nov 23 '05 #8
Oh, and you need to declare TextLengthDelegate also:
public delegate int TextLengthDelegate(Control ctrol);

Hope it helps,
Thi

Nov 23 '05 #9
I was doing a lot more than just testing textlength... I ended up trying
this line inside of my triggered event instead:
this.txt_log.Invoke( ProcessMessage, new object[] { sMsg } );

Where ProcessMessage was another event, and this line forces the message
to be run on the txt_log thread, making everything ok :)

Thank you both for your help in pointing me in the right direction!

Truong Hong Thi wrote:
Oh, and you need to declare TextLengthDelegate also:
public delegate int TextLengthDelegate(Control ctrol);

Hope it helps,
Thi

Nov 23 '05 #10
D. Yates wrote:
Benny,

Sure. Just use the BeginInvoke method on the event, which will spawn
off a thread pool thread to service this call, and your thread will
go on its marry way. Just remember that if there are more than one
items in the invocation list inside of the event (see
GetInvocationList of the event) that you have to iterate through them
all and call BeginInvoke on each.


Yes, but the documentation does say that you should call EndInvoke at
some point (to do clean up), which means that it is not entirely
fire-and-forget. To have fire-and-forget you must add [OneWay] to the
method that is called through the delegate.

Richard
--
http://www.grimes.demon.co.uk/workshops/fusionWS.htm
http://www.grimes.demon.co.uk/workshops/securityWS.htm
Dec 4 '05 #11
So where should the [OneWay] go? Here's my delegate/event:
#region Delegates and Event Declarations > MessageReceived Event
public delegate void MessageReceivedEventHandler(ServerMessage sMsg);

public event MessageReceivedEventHandler MessageReceived;
// [OneWay] goes here?
private void OnMessageReceived(ServerMessage sMsg)
{
if (MessageReceived != null)
{
MessageReceived.BeginInvoke(sMsg, null, null);
}
}
#endregion

Richard Grimes wrote:
D. Yates wrote:
Benny,

Sure. Just use the BeginInvoke method on the event, which will spawn
off a thread pool thread to service this call, and your thread will
go on its marry way. Just remember that if there are more than one
items in the invocation list inside of the event (see
GetInvocationList of the event) that you have to iterate through them
all and call BeginInvoke on each.

Yes, but the documentation does say that you should call EndInvoke at
some point (to do clean up), which means that it is not entirely
fire-and-forget. To have fire-and-forget you must add [OneWay] to the
method that is called through the delegate.

Richard

Dec 5 '05 #12
Benny Raymond wrote:
So where should the [OneWay] go? Here's my delegate/event: public delegate void MessageReceivedEventHandler(ServerMessage sMsg);

public event MessageReceivedEventHandler MessageReceived;
// [OneWay] goes here?
private void OnMessageReceived(ServerMessage sMsg)
{
if (MessageReceived != null)
{
MessageReceived.BeginInvoke(sMsg, null, null);


It should go on whatever method(s) that MessageReceived contain. Yes I
know it is a pain if you don't own that method. The solution there is to
write a wrapper method that calls the method synchronously and put
[OneWay] on the wrapper method and call the wrapper method
asynchronously.

[OneWay] void Wrapper(int param)
{
MethodIDontOwn();
}

delegate void MyDelegate(int param);

MyDelegate del = new MyDelegate(Wrapper);
del.BeginInvoke(param, null, null);
// don't need to call EndInvoke

Richard
--
http://www.grimes.demon.co.uk/workshops/fusionWS.htm
http://www.grimes.demon.co.uk/workshops/securityWS.htm
Dec 5 '05 #13

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

Similar topics

1
by: Dan Cimpoiesu | last post by:
I have a remoting object, derived from MarshalByRefComponent, that I instantiate on the client side, with Activator.GetObject. Can I receive events fired on the server, on the client? How?
2
by: ZAky | last post by:
Why do I get a System.NullReferenceException for this script? I added the following script to a simple form with a button. <Script> public event EventHandler DoThis; static void Main() {...
0
by: Thanh Nguyen | last post by:
Hi everyone, I'm encountering a very weird problem, I have spent the last 3 days trying to figure out how to fix but there is still no clue. Here is the problem: I define 2 WebUserControls: -...
12
by: Vittorio Pavesi | last post by:
Hello, is it possible to manually raise the event Elapsed of the timer object ? Vittorio
4
by: Jeremy | last post by:
I have a combobox with a SelectionChangeCommitted event handler, and am having a problem raising this event. For example, raiseEvent mycombobox.SelectionChangeCommitted gives me an error...
1
by: Anonieko | last post by:
I know Visual Studio lacked support on easily writing code to raise events from a ascx user control ( because you have to hand write them)....
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...
3
by: =?Utf-8?B?Ulc=?= | last post by:
I constructed a new Class with some private members. I would like an event to be raised on the moment the value of one of those private members is changed. How do I define an event for that...
5
by: Mike | last post by:
Hi group; Let say I have an object called Account, that raises an event called AccountLow with its owns EventArgs, and when this event gets raised, I will like to raise another custom...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
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...

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.