472,804 Members | 892 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,804 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 2828
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...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 2 August 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
linyimin
by: linyimin | last post by:
Spring Startup Analyzer generates an interactive Spring application startup report that lets you understand what contributes to the application startup time and helps to optimize it. Support for...
0
by: erikbower65 | last post by:
Here's a concise step-by-step guide for manually installing IntelliJ IDEA: 1. Download: Visit the official JetBrains website and download the IntelliJ IDEA Community or Ultimate edition based on...
0
by: Taofi | last post by:
I try to insert a new record but the error message says the number of query names and destination fields are not the same This are my field names ID, Budgeted, Actual, Status and Differences ...
0
by: Rina0 | last post by:
I am looking for a Python code to find the longest common subsequence of two strings. I found this blog post that describes the length of longest common subsequence problem and provides a solution in...
5
by: DJRhino | last post by:
Private Sub CboDrawingID_BeforeUpdate(Cancel As Integer) If = 310029923 Or 310030138 Or 310030152 Or 310030346 Or 310030348 Or _ 310030356 Or 310030359 Or 310030362 Or...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
0
by: Mushico | last post by:
How to calculate date of retirement from date of birth
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...

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.