|
Nice answer. The only thing I think I could do differently in the first option is use an AutomaticResetEvent or a ManualResetEvent to specify a drop dead time, that way you can track which modules didn't complete as well as not worry about the decrement variable not reaching zero. And definitely use the Interlocked class. The second option would probably be more reliable. IMHO.
Scott P
"Run for your life from any man who tells you that money is evil. That sentence is the leper's bell of an approaching looter." --Ayn Rand
|
|
|
|
|
Thanks guys, sound like really good ideas to try.
Scott, i read about the AutoResetEvent and ManualResetEvent but i don't understand what it does and how to use it in my case. Could you please give an example?
How does the event thing works in this case:
The host creates a new thread for the StartWork() method of the module class.
At the end of the method it fires an event which is handled by the host.
Now in this case as i understand the event handler is run in the module thread, am i correct?
What i thought about is to go with the collection idea first and add an event handler to the OnRemoved event (assuming there is one, otherwise i can build my own collection class). If the OnRemoved event is handled in the parent thread then this is perfect but otherwise it's a problem.
What do you think?
darthBug
Join the dark side of the code
|
|
|
|
|
Read the source code below. Not quite production, but you'll get the idea on how the ManualResetEvents work.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ManualResetExample {
public class MockModule {
public MockModule(String name) {
Name = name;
}
public String Name { get; private set; }
private Object syncLock = new Object();
private EventHandler onDone;
public event EventHandler OnDone {
add {
lock (syncLock) {
onDone += value;
}
}
remove {
lock (syncLock) {
onDone -= value;
}
}
}
private void FireOnDone(Object sender, EventArgs args) {
if (onDone != null) {
onDone(sender, args);
}
}
public void StartWork() {
ThreadPool.QueueUserWorkItem(new WaitCallback(WorkThread));
}
private void WorkThread(Object arg) {
try {
for (int i = 0; i < 5; i++) {
Thread.Sleep(250);
Console.WriteLine("{0} working", Name);
}
} finally {
FireOnDone(this, new EventArgs());
}
}
}
public class WorkCompleteEventArgs : EventArgs {
public WorkCompleteEventArgs(Boolean wasSuccessful) {
Success = wasSuccessful;
}
public Boolean Success { get; private set; }
}
internal class ModuleSyncBlock {
public ModuleSyncBlock(MockModule module) {
Reset = new ManualResetEvent(false);
MockModule = module;
}
public ManualResetEvent Reset { get; set; }
public MockModule MockModule { get; set; }
}
public class ModuleManager {
List<modulesyncblock> modules;
List<mockmodule> mocks;
public ModuleManager() {
modules = new List<modulesyncblock>();
mocks = new List<mockmodule>();
mocks.Add(new MockModule("One"));
mocks.Add(new MockModule("Two"));
mocks.Add(new MockModule("Three"));
mocks.Add(new MockModule("Four"));
mocks.Add(new MockModule("Five"));
}
public void StartAll() {
ThreadPool.QueueUserWorkItem(new WaitCallback(RunInternal));
}
private void RunInternal(Object arg) {
List<manualresetevent> manuals = new List<manualresetevent>();
mocks.ForEach(m => modules.Add(new ModuleSyncBlock(m)));
modules.ForEach(m => manuals.Add(m.Reset));
modules.ForEach(m => {
m.MockModule.OnDone += new EventHandler(MockModule_OnDone);
m.MockModule.StartWork();
});
if (WaitHandle.WaitAll(manuals.ToArray(), new TimeSpan(0, 0, 30), false)) {
FireOnWorkComplete(this, new WorkCompleteEventArgs(true));
} else {
FireOnWorkComplete(this, new WorkCompleteEventArgs(false));
}
}
void MockModule_OnDone(object sender, EventArgs e) {
ModuleSyncBlock msb = modules.Find(m => ReferenceEquals(sender, m.MockModule));
if (msb != null) {
Console.WriteLine(msb.MockModule.Name + " Finished");
msb.Reset.Set();
}
}
private Object syncLockA = new Object();
private EventHandler<workcompleteeventargs> onWorkComplete;
public event EventHandler<workcompleteeventargs> OnWorkComplete {
add {
lock (syncLockA) {
onWorkComplete += value;
}
}
remove {
lock (syncLockA) {
onWorkComplete -= value;
}
}
}
private void FireOnWorkComplete(Object sender, WorkCompleteEventArgs args) {
if (onWorkComplete != null) {
onWorkComplete(sender, args);
}
}
}
}
</workcompleteeventargs></workcompleteeventargs></manualresetevent></manualresetevent></mockmodule></modulesyncblock></mockmodule></modulesyncblock>
"Run for your life from any man who tells you that money is evil. That sentence is the leper's bell of an approaching looter." --Ayn Rand
|
|
|
|
|
Where do you guys (and girls) typically put the definition of an enum in your code? I have generally placed mine just inside the namespace instead of inside a class. It seems like the namespace is getting cluttered with enumerations.
Thanks for your comments!
Hogan
|
|
|
|
|
I typically create them in the namespace. I like having them seperated one class/enum per file so I can easily find them if I need to update them.
Broken Bokken
You can't carry out a ninja-style assasination dressed as an astronaut. It's the luminous fabric; too visible. - Tripod
http://www.brokenbokken.com
|
|
|
|
|
Hey,
I keep 'em the same way, one class per file and a bunch of enums in their own file under the same namespace.
darthBug
Join the dark side of the code
|
|
|
|
|
Interesting idea. Currently we just throw em at the top of whatever file they are needed at. It forces us to search through the code more. I'll have to look into that one file for enums idea.
Hogan
|
|
|
|
|
Same here, all in one file. I typically twiddle with enums much less, and it cuts down on the clutter in the project.
Scott P
"Run for your life from any man who tells you that money is evil. That sentence is the leper's bell of an approaching looter." --Ayn Rand
|
|
|
|
|
Hi Guys. I am trying to match some input from a text box to an if statement. Now, I am doing this from following some ARL code and I get a build error. Error message is "Operator '>=' cannot be applied to operands of type 'string' and 'string'"
The ARL code looks something like this.
if ws_holder_pcode >= 4731 and ws_holder_pcode <= 6499
begin
move 1 to ws_holder_province
finish
end
What I have written in the button click event.
private void btnValidate_Click(object sender, EventArgs e)
{
if (txtboxPcode.Text >= "4731" && txtboxPcode.Text <= "6499")
{
MessageBox.Show("Eastern Cape");
}
}
How can I do this correctly? Any suggestions would be greatly appreciated.
Excellence is doing ordinary things extraordinarily well.
|
|
|
|
|
To compare strings, try the String.Compare() method.
private void btnValidate_Click(object sender, EventArgs e)<br />
{<br />
<br />
if (String.Compare(txtboxPcode.Text,"4731") == 0 && String.Compare(txtboxPcode.Text,"6499") == 0)<br />
{<br />
MessageBox.Show("Eastern Cape");<br />
}<br />
}
Just because we can; does not mean we should.
|
|
|
|
|
Thanks mate. I actualy want to check that the value entered falls in the range of 4731 and 6499.
KaptinKrunch wrote: if (String.Compare(txtboxPcode.Text,"4731") == 0 && String.Compare(txtboxPcode.Text,"6499") == 0)
I have tried the suggestion that you made but I keep getting "Invalid Pcode" message returned from the else statement meaning that I am not making a match. So, what I want to do is something like this.
if (txtboxPcode.Text >= 4731 && txtboxPcode.Text <= 6499)
{
MessageBox.Show("Eastern Cape");
}
Any further suggestions appreciated.
Excellence is doing ordinary things extraordinarily well.
|
|
|
|
|
You could change your strings "6499" to Int32's and convert the contents of your text boxes to int's by Int32.Parse(box.Text);
and don't forget to put in the IFormatProvider to the Parse method.
Scott P
"Run for your life from any man who tells you that money is evil. That sentence is the leper's bell of an approaching looter." --Ayn Rand
|
|
|
|
|
Keep in mind too that your if logic is stating that your textbox value needs to equal both 4731 and 6499. If you need to match one or the other, change the operator to "||"(OR) vs "&&"(AND).
Just because we can; does not mean we should.
|
|
|
|
|
If the value entered falls within the range of 4731 and 6499 i.e. the user enters 5000 then a amtch is made. Maybe I am writing it wrong. If the value entered falls anywhere inbetween then we have match.
Excellence is doing ordinary things extraordinarily well.
|
|
|
|
|
private void btnValidate_Click(object sender, EventArgs e)
{
int pcode = 0;
if (int.TryParse(txtboxPcode.Text) == false)
{
MessageBox.Show("Invalid Integer!");
return;
}
if ((pcode >= 4731) && (pcode <= 6499))
{
MessageBox.Show("Eastern Cape");
return;
}
MessageBox.Show("Unknown Cape!");
}
|
|
|
|
|
Ed.Poore wrote: if (int.TryParse(txtboxPcode.Text) == false)
Thanx Ed.Poore. You however left out the out portion of the statment. I amended it to look like this and it worked fine.
private void btnValidate_Click(object sender, EventArgs e)
{
int pcode = 0;
if (int.TryParse(txtboxPcode.Text, out pcode) == false)
{
MessageBox.Show("Invalid Integer!");
return;
}
if((pcode >= 4731) && (pcode <=6499))
{
MessageBox.Show("Eastern Cape");
}
Thanks for the help mate. Greatly appreciated.
Excellence is doing ordinary things extraordinarily well.
|
|
|
|
|
hy everyone!
sorry for me asking again, but i encountered two additional problems during realizing my parser:
problem number one:
after i finished parsing, there might be some fields which weren't replaced by it's values. they are of a special format
< format|varname|format >
in this example format has to be replaced by a format value which i defined myself.
*) there could be 0 to n "#" which define the fieldlength and right- or leftalignment (e.g. <###|varname|> for rightalignment of a filed with length 3 - because of 3 #s) <|varname|###> would be the counterpart but leftalignment.
*) there could be a formatstring on the right e.g. <|varname|{#,##0.00}>
*) there could be 0 to n "~" which define the string to be centered and define the fieldlength e.g. <|varname|~~~> for fieldlength 3 and centering
*) and there could be either a sign "]" or "[" on the right which define on which page the variable should be replaced by it's value or by an empty string. e.g <|varname|[>
and (which makes it even harder and causes my second problem) a combination of the formatings above (except left-, rightalignment and center at the same time!) in not defined order (but not mixed!). e.g. <###|varname|{##0.00}[> (but not e.g. <|varname|~~[~~> etc.)
so i have to replace strings between < and > without knowing whats inbetween by an "empty" string (but of defined length, if # or { is found!).
my solution would be to search the final parsed string for an occurence of "<" and then parse in the string until the ">" is found. then do the formating for # and ~ but ignoring all other formatings).
but if i have to do this more often then this could be of bad performance because the more often i do change a string the longer it will take (i guess even when using a stringbuilder).
problem number 2:
well but this is not my only problem. my other problem is to do the formating in general if there are more than one format value on one side.
i allowed # to be on the left and right but all other values just to be on the right. so the left side is easy. but the right is not.
so my idea would be to first parse from the index i get for the start of the variable (e.g. |varname|) and then parse to the left until i reach the "<" sign. this info will be stored in a variable called e.g. string leftformat. then i do the same at the right by parsing from index + lengthofvariable (so from the first sign after |varname|) again until i reach the ">" this time. well, this side is tricky, because i have to check for more possible signs: "#" or "~", a format string {...} and a sign "[" or "]" (the ors are exclusive in this case so either this or that but not at the same time!). then i would put the right side into a loop until the rightformat string is parsed (empty, or length index). in this loop i would check for all possible signs, which could be there. but i do not know in which order they might occur, that's why i do the loop. because i could check for the sign sequentially. so if the last if is the one then i have to repeat the check for the next signs.
example for the right side: #####{##0.00}[
(note that the #s in the formatstring are treated differently, because they are sourounded by "{" and "}"!!).
so my could would look like (pseudocode!)
while (string not empty or i < length)
{
if char == "#" { while still "#" replace this one }
if char == "~" { check needed if "#" was alreaday used!
while still "~" replace this one}
if char == "{" { parse until the "}" sign is reached }
if char == "[" { do the operation }
if char == "]" { check if not already "[" and do the operation }
}
well i hope i did describe my problems well enough but not to long on the other hand side
what do you think about this? from my point of view i am not sure if this doesn't slow down my parser too much. that's why i posted it here for discussion and further ideas.
so if anyone of you has comments or any better solution to handle this, please let me know by replying to my post.
thanks.
stephan.
modified on Thursday, April 24, 2008 12:54 PM
|
|
|
|
|
I think regular expressions are about to become your new best friend.
Just because we can; does not mean we should.
|
|
|
|
|
I don't think reg expressions become anyones best freind. I see it more like an annoying tenant that won't move out, yet gives you lots of money at the end of the month. If you see what i mean.
My current favourite word is: Bacon!
-SK Genius
|
|
|
|
|
what is the main class in C#.net from which all the classes are
derived?
please someone answer my question i am new to C#.thanks
aayzgroup
|
|
|
|
|
Please, don't fill up the forum with lots of simple questions, you could have used one post to ask all of them.
Also, you can easily use google to find the answers you are looking for, and it would probably be quicker as well.
Since you are asking these questions i recommend that you buy a beginners book, and if you don't want to spend any money, start working through a set of online tutorials - there are plenty available.
My current favourite word is: Bacon!
-SK Genius
|
|
|
|
|
SK Genius wrote: don't fill up the forum with lots of simple questions, you could have used one post to ask all of them.
It depends on your preference. I prefer each thread to contain only one question.
|
|
|
|
|
Yep, I was gonna say that too, but you know, when you're preparing for an interview where you plan to say you know a language you don't know... it's best not to waste too much time on that...
|
|
|
|
|
A@YZ wrote: what is the main class in C#.net from which all the classes are
derived?
If by "main" you mean "base" then it is object . All classes are, eventually, derived from object .
|
|
|
|
|
"In the beginning there was the class , and the class was object ."
|
|
|
|