Event assigned but doesn't fire

M

Mark Nijhof

Hi,

A quicke summarize:
I made a windows form that can set up a socket connection. It also has
events that fire when data arives. Now I am using this form in a hidden
way inside other code (was the only way I could get the threading to
work for the client without the client needing to test for thread save
stuff) It works in several programs (perfectly), but in a Windows
Services it doesn't fire the event. I used debug lines to check what
went on, it gets to the fireing of the event akts normal (no error) but
the event doesn't get fired.

When I insert this into a windows form I can access the GUI without
getting a conflict about accessing a GUI element from a different thread
than the creator.

private void ServerDataReceived(string Message)
{
if (InvokeRequired)
{
object[] pList = { Message };
ReceivedDataTextBox.BeginInvoke(new
UpdateServerCallback(DoServerDataReceived), pList);
}
else
{
DoServerDataReceived(Message);
}
}
private void DoServerDataReceived(string Message)
{
ReceivedDataTextBox.Text = Message;
if (OnMessageReceivedFromServer != null)
{
OnMessageReceivedFromServer(this, Message); <-- It just walks over this
line, no error no event ...
}
else
{
Log.LogError("No one is listening to OnMessageReceivedFromServer");
}
}


If anybody know what goes on here or can help me find out what to check,
please :)

-Mark
 
N

Nicholas Paldino [.NET/C# MVP]

Mark,

If you are running this code in a service, you should not be using a
windows form. You should separate the logic out of the form into other
classes which you can use with your service.

The thing with a service is that it is not guaranteed that there is an
interactive user session that is running which you could attach to in order
to create windows in (and you have to set the service up to specifically
allow that as well).

Bottom line, separate out the logic from your form into classes that you
can use in your service.

Hope this helps.
 
M

Mark Nijhof

Hi Nicholas,

Thanks for the reply :)

I probably wasn't clear about it, I know it is not the way to do it to
use a Windows Form in a Windows Services. The reason why I do that is
that I want to do the thread syncronasation inside the class. I want to
be able to place this component any where without having to worrie about
the threading part. So that the end user doesn't have to write the
Invoke part when using the component in a GUI enviorment. I am not
Showing the form anywhere, I just need it's capabilities to check wheter
the call is from a different thread.

If you know a way arround it not having to use Windows.Forms than that
would be great.

-Mark
 
J

Jon Skeet [C# MVP]

Mark Nijhof said:
Thanks for the reply :)

I probably wasn't clear about it, I know it is not the way to do it to
use a Windows Form in a Windows Services. The reason why I do that is
that I want to do the thread syncronasation inside the class. I want to
be able to place this component any where without having to worrie about
the threading part. So that the end user doesn't have to write the
Invoke part when using the component in a GUI enviorment. I am not
Showing the form anywhere, I just need it's capabilities to check wheter
the call is from a different thread.

If you know a way arround it not having to use Windows.Forms than that
would be great.

Basically, you should write an equivalent of a message pump - or
another way of looking at it is a thread-pool with only a single thread
in it.

You just need to wait for data (whether that's in terms of parameters
or delegates or whatever) and use something like Monitor.Wait/Pulse to
get notified when that data arrives.

See half way down
http://www.pobox.com/~skeet/csharp/threads/deadlocks.shtml for an
example of a producer/consumer queue which could be handy here. I'd
also suggest implementing ISynchronizeInvoke so that you could pass an
implementation of that around (just as ISynchronizeInvoke) for clients
to use.
 
N

Nicholas Paldino [.NET/C# MVP]

Mark,

What you want to do is not really possible without some knowledge of the
environment that you are running in. You sound like you want thread
affinity, not thread synchronization. This is what the ISynchronizeInvoke
interface is for.

Instead of handling that inside your class, I would have your class take
an implementation of ISynchronizeInvoke (through the constructor, on a
property, etc, etc) and then use that to invoke your methods on the
appropriate thread. If it is not passed in, then you execute it on whatever
thread you are called on.

This way, you can pass a control so that you can have your method
execute on the UI thread (be careful about doing this, good design is going
to be important here).

Also, as a general rule, you don't want to encapsulate all of this
threading in a component so that it is black-boxed. Rather, it should be up
to the caller, or the caller should have explicit knowledge of how the
threading is occuring, and affect it, if desired.
 
M

Mark Nijhof

Thanks Jon and Nicholas,

I will look into these suggestions first thing tomorrow, I have been
looking arrount too find a better option for this for a while.

Why would you not want to have a black box principle? (it's not for a
comercial product, just trying, learning and understanding) I just want
to have to create the component and I have a socket connection than
listenen for the event and do what I want to do there, wether there is a
gui involved or not.

Thanks for the help, keep watching this toppic, I'll most likely be back
;)

-Mark
 
N

Nicholas Paldino [.NET/C# MVP]

Mark,

In programming, black boxes are rarely good things. More often than
not, you find that requirements change, and when things are encapsulated in
such a way, you will have a harder time pulling it all out later. In the
end, the future maintainability is compromised when you do something like
this.

Of course, it is possible that there are conditions that will never, or
are very unlikely to change. If that is the case, then I would assume that
pulling this all together in a black-boxed method would be ok. You are the
only one who can make that decision.

Also, don't reply to this thread. Chances are if you take more than 1/2
a day to respond, it will have scrolled too far up the list (for those that
don't track individual threads) that no one will see it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top