|
I'm a C# noob so I apologize if I say something stupid or unclear.
I have a class that contains a thread that sits there in a loop, considering the world. Every once in a while, it decides that it needs to alert the world to some idea it has, so it calls its delegate function, sends information to all of its clients, who get the information via event handler functions that they've "+="'d to the delgate.
If this class didn't incorporate a thread, I would be done here, and everything would work perfectly. My class's clients would add a handler to the class's delegate when they feel like listening to it jabber, and they would periodically receive data and do whatever they want with it.
The terrible problem is that you can't ordinarily mess with controls if you aren't in the control's originating thread, so you need to use "Invoke".
If I understand correctly, one way to deal with this would be to have all the clients realize they are dealing with a class that is kind of toxic, and have all handlers that sign up with my class call "Invoke" whenever they are called. Essentially, the clients would realize that they are operating from within a foreign thread, and they would take appropriate precautions.
I don't like this solution, because the clients shouldn't have to know that they are being called from a different thread. They should just be able to add a handler and get data from the class, and everything should work.
Also, I could have some performance issues here, since future instances of my class might not use a thread, and I'd be stuck with all of this old ugly code that uses "Invoke".
Another way to deal with this is for the class itself to use "Invoke" on the delegate. I haven't thoroughly tested this, but it compiles and apparently runs, at least when there is only one client.
The drawback to this is that when I create the class, I have to pass in the form that created the class, so there will be an object to use to call invoke. This is ugly, and also I expect it would mess up if another thread added a handler to my class.
Question:
What is the best way to deal with events that are generated from within a thread, so that the clients work correctly, don't have to know that they are dealing with a thread, and don't have to pass difficult to explain parameters around?
Thank you,
bruce
|
|
|
|
|
Can I just use the "BeginInvoke" method on the delegate, and dummy out the 2nd and 3rd parameters? This is what I'm doing now, and it also compiles and runs.
bruce
|
|
|
|
|
Okay, this idea is wrong, I can see it coming in on a different thread.
bruce
|
|
|
|
|
You can subscribe to an event from a different thread. You just cannot use a System.Windows.Forms.Control from a thread other than the UI thread.
Tech, life, family, faith: Give me a visit.
I'm currently blogging about: Cops & Robbers
Judah Himango
|
|
|
|
|
|
I'll describe it a little differently.
I have a black box. Code subscribes to the black box by adding event handlers to the delegates that are the visible interface of the black box.
Maybe the black box uses threads, and maybe it doesn't. It's a regular class now but eventually it will be an interface class, and some of the derived classes I have in mind will not use threads. In any case, the subscribers ideally should not have to care. They should just sit back and wait, and when their event handlers fire, they should fire in the same thread that they are sitting in, because doing otherwise is about as polite as dumping coffee in their lap.
The generic event invoker you provide would work. It's pretty much what I do now, but the problem is that ISynchronizeInvoke object. As far as I know I can't make one of those on the fly. I have to pass one in, probably as an argument to the constructor of the black box. And unless I am misunderstanding C# reality, which is certainly likely since I have been doing C# for about a week now, the one I pass in won't necessarily apply to all of the events attached to the delegate.
I think that I have two choices:
1) Do it as you suggest, which results in a "control" or "form" parameter being passed in to my black box, and which results in my being able to accept customers from one thread only.
2) Make sure that all of the black box customers are aware that I'm going to stab them in the eye by calling into their event handler code from a different thread. This is weird and unpleasant code, but it would work, and the black box itself is clean.
I think I would lean toward the first solution, because the oddball code is in the black box, where it where it should be.
I wish there was another solution -- that it was possible to call a delegate in such a way that all of the event handler calls magically found their way back to the correct thread.
Thank you again,
bruce
|
|
|
|
|
Look at System.Timers.Timer to see how the CLR developers dealt with the problem. I'm not saying it's a great solution, but this is essentially what the "standard" solution to the problem is.
The way I view it is that thread safety is part of an objects interface or contract. There is just no way around it, there is just too much overhead with making every object thread safe to make it a default.
I can imagine the sinking feeling one would have after ordering my book,
only to find a laughably ridiculous theory with demented logic once the book arrives - Mark McCutcheon
|
|
|
|
|
It appears that in that timer, you get called from some random thread, so if you are going to use that timer, you have to be smart about dealing with the consequences.
"Invoke" is sounding like it uses the modern equivalent of "PostMessage", which wouldn't be available unless you associate a form with it, I'm guessing. It doesn't sound like there is some magic call I can make that will get me back into the UI thread unless I go to the trouble of remembering where the UI thread is.
In case there is some confusion, I didn't start this thread to whine about .NET. I spent time trying to figure out how to solve my problem, and solved it, in a way that wasn't very elegant. The reason I wrote the post was to figure out if there was a obvious and elegant solution that I was missing.
It sounds like there isn't one, which is fine.
Thank you to everyone who replied.
bruce
|
|
|
|
|
Hi All,
I have a very specific requirement. I have noticed in some websites and windows apps which use a control placed beside a text box. It has a small "^" button and "v" button. pressing "^" increments the value in the text box and pressing "v" decrements the value.
What control could be used for that.
All suggestions are welcome.
All help is great Help.
Thanks in advance.
SJ
|
|
|
|
|
Looking in the toolbox I see: NumericUpDown.
---
b { font-weight: normal; }
|
|
|
|
|
Hey guys, could someone give me a tip, how to distinguish between send and receive data in a terminal program ? What I want to do is, I will write my own terminal program, like tera term - in C#. But one issue to me is how could I distinguish between data I've written into the textbox and sent this data via com-port and data which is received via com-port and written into the textbox. The event to update the textbox is textchange, maybe I should use an other event but which? Thnak's for your help.
|
|
|
|
|
Hello,
I have a string: str = "1~2~1";
Also I have a statement:
DataRow[] cashRows = this.dataset.Tables["CashFlow"].Select ("IndentLevel = "+str);
It gives me an error, that the expression contains unsuppoerte operator '~'. Is there a way of making the select statement work?
Thank you.
|
|
|
|
|
Just a guess, do you need to escape the ~ "1\~2\~1"
|
|
|
|
|
DataRow[] cashRows = this.dataset.Tables["CashFlow"].Select ("IndentLevel = '" + str + "'");
|
|
|
|
|
I am installed ActiveReports and I cannot see the viewer icon and where on the tool box. Mt Question is, how do I add the ActiveReports viewer control to my Visual Studio toolbox.
Thank you all.
Nana
|
|
|
|
|
I'm having problems with a get/set property, and I want to know how to use it. Declaration in the library where it is says this:
public abstract new bool Mute [ get, set ]
Member of Microsoft.MediaCenter.Extensibility.AudioMixer
Thanks in advance,
Theo
|
|
|
|
|
*edit* Woops, just looked it up, it's a native .NET library. Cool . So just add a reference to Microsoft.MediaCenter.dll in your Visual Studio project, then go something like:
using Microsoft.MediaCenter.Extensibility;
...
AudioMixer mixer = AddInHost.AudioMixer;
bool isMuted = mixer.Muted;
mixer.Muted = true;
Tech, life, family, faith: Give me a visit.
I'm currently blogging about: Cops & Robbers
Judah Himango
|
|
|
|
|
This code does not work Keep in mind the AudioMixer is an interface, not a class.
|
|
|
|
|
Ok, you didn't ask how to get the AudioMixer, so I assumed you already knew. The article I linked to has some examples; I don't know offhand because it's a 3rd party extension that I've never used before. I suggest you create another post if you need help creating the AudioMixer.
Tech, life, family, faith: Give me a visit.
I'm currently blogging about: Cops & Robbers
Judah Himango
|
|
|
|
|
I am trying to find a way to remove data from a file using C#.
I know how to edit using FileStream.Seek and a StreamWriter, and I know how to append data to the end, but I haven't found a way to actually remove data from the end of a file.
Due to file size and memory constraints, reading the whole thing in, saving it as a new file, and then deleting the old file is not an option.
Is there a way to write an EOF where I specify, and that's that? (if so, how do you actually do that?) Or do I have to go about doing this some other way?
Thanks in advance for the help,
Jonathan Mitchem
|
|
|
|
|
No matter what you do, you'll have to get the file stream. This is standard. You can Seek to a position (or .Position) the position of the stream, write data to it, then save it, overritting the previous file. That's probably your best bet.
Tech, life, family, faith: Give me a visit.
I'm currently blogging about: Cops & Robbers
Judah Himango
|
|
|
|
|
|
Use the SetLength method of the FileStream class.
---
b { font-weight: normal; }
|
|
|
|
|
I have a control inherited from ComboBox. In constructor I add some items. Now, when my control is have been putted onto form designed calls to constructor and item collection is automatically updates. How can I prevent this action, some directive or attribute that tells to designer not to call to constructor during the design time?
|
|
|
|
|
Please see this page[^] for information about how to write design-time aware code.
Also, the designer will always call the default constructor (i.e. the constructor that takes zero parameters). If you want to create a constructor that gets called only by your code, create a second constructor that takes a parameter.
Tech, life, family, faith: Give me a visit.
I'm currently blogging about: Cops & Robbers
Judah Himango
-- modified at 13:30 Thursday 15th September, 2005
|
|
|
|
|