|
I've decided to just use EventArgs containing a reference to the appropiate object whenever it is called. Probably not very elegant, but it works, at least.
It seems that anonymous methods have the scope of the creation place, but I'd have to do some research to say for certain...
|
|
|
|
|
That is probably the sensible solution. But I still hope someone can help shed light on this; I've discovered something I'm unsure about and that is always an opportunity to learn.
I could probably google it, but if someone has the answer at hand...
|
|
|
|
|
I've checked it.
It always has the scope of the place where it was created.
public void init()
{
int i = 30;
foo(delegate()
{
i = 10;
});
Console.WriteLine("i = " + i.ToString());
Console.ReadKey();
}
public void foo(EventHandler awesome)
{
awesome();
}
This would return "i = 10". This is somehow creepy, because it's a variable local in another method...
The same happens if foo is in another class.
Additionally, if the creator object doesn't exist anymore... nothing happens:
using System;
using System.Collections.Generic;
using System.Text;
namespace test2
{
class Program
{
static void Main(string[] args)
{
Thing1 thing1 = new Thing1();
Thing2 thing2 = thing1.Get2();
thing1 = null;
GC.Collect();
thing2.awesome(null, null);
return;
}
}
public class Thing1
{
public Thing2 Get2()
{
Thing2 thing2 = new Thing2();
thing2.awesome = delegate(object sender, EventArgs args)
{
thing2 = null;
};
return thing2;
}
}
public class Thing2
{
public EventHandler awesome;
}
}
Cleary, thing1 created the anonymous delegate.
I've named the Thing2 variable the same everywhere, to be sure.
Main.thing2 didn't turn into null, therefore it affected the non-existing thing1, ie. nothing happened. Also, no crash nor anything of that sort. It obviously has the scope of Thing1.Get2(), again the creator scope.
[Edit]
I've just noticed. The Garbage Collection doesn't take thing1!
The anonymous delegate points to it after all...
modified on Wednesday, July 1, 2009 2:20 PM
|
|
|
|
|
Thanks for that! But here too the delegate executes before the containing function returns. It's an EventHandler delegate, but it's used as any other delegate - there's no event.
Using an anonymous method for an event handler isn't necessarily weird, but accessing variables that are scoped to the containing method from the event handler is very weird indeed. I did a quick test to see how this behaved with a windows forms app. In the constructor I go into a loop to make 5 buttons, and I attach an anonymous method to the Click event. In the handler I show a messagebox displaying the value of the loop variable. I figured if the method was supposed to somehow "see" the external variable when I press a button, which I think we can agree won't happen until after the constructor has finished, then it would mean that five anonymous methods and five copies of this external variable had to be created. What actually happens though is that clicking any button shows the value 5, so presumably there is only one copy of the method.
What I am now wondering is where the heck this external variable lives. Normally local variables live on the stack, but if this one did it would have died when the constructor returned. So I presume it's on the heap somewhere. I'm not sure I like this.
My test code:
public Form1()
{
InitializeComponent();
for (int i = 0; i < 5; i++)
{
Button b = new Button() { Text = "button" + i, Top = 30*(i+1), Left = 50 };
Controls.Add(b);
b.Click += delegate(object sender, EventArgs e)
{
MessageBox.Show("variable i (scoped to Form1 constructor!) = " + i);
};
}
}
|
|
|
|
|
After these new insights, I guess I'll have to avoid relying on anonymous methods too much. This sounds like a lot of painful, difficulty-to-pin-down bugs, should something go wrong... :/
|
|
|
|
|
I am new to C# and have been testing many features in a single project. Now that I have tested and refined what I have done I would like to "copy" the classes, forms and some other information to a new (non cluttered) project. What is the the best way of going about this. Copy the whole project folder to a new project folder and take out the things I don't need??
Thanks for you help.
|
|
|
|
|
Visual Studio has an "Add existing..." feature.
Create your new project, and right-click the project in the Solution Explorer, select "Add" -> "Existing Item...".
Don't manually shift around stuff, *ever*.
modified on Wednesday, July 1, 2009 3:24 AM
|
|
|
|
|
Narvius wrote: Don't manually shift around stuff, *ever*.
How I wish we didn't have to! Alas, there are times when Visual Studio and Visual SourceSafe conspire to make manual interventions the only option, such as if a project under source control is to be renamed.
With luck these issues will simply go away when we eventually move to Team System...
While I'm on it bitching about source control, the "web project without a project" is the worst idea I've come across this far. Surely it would be possible to have a project file and still use the dynamic compilation model? Now, if my web app has the audacity to write a log file (or any file really) anywhere under the web site root, Visual Studio very cleverly decided this is a "newly added file" and proceeds to add it to the SourceSafe database if I check in the solution. I wonder who's great idea that was!
Oh well. :§
|
|
|
|
|
Hi,
I made an installer using the VS 2005 setup and deployment project. I made a custom installer class and overrode the Install, Uninstall and Rollback methods. I installed my program, which worked, but when I tried to uninstall it, there was an exception. Now I don't know how to uninstall my program. Also, I don't know how to debug the installer.
If anyone could provide some insight, it would be much appreciated.
Thank you very much
choo_chu
|
|
|
|
|
And the exception would be...
|
|
|
|
|
Hi EliottA,
The exception is "can't write to registry key". I forgot to set the boolean value to true to make the registry key writeable. By default it is false...not writeable.
choo_chu
|
|
|
|
|
To clarify, the problem you're running into is that the custom action throws an unhandled exception, the uninstaller catches it and rolls back the uninstallation process. This effectively disallows you from uninstalling your own package. Is this correct?
If so then what the exception is is irrelevant, the important part is that your custom action needs catch EVERYTHING or else you run into the problem you're experiencing. To get your program uninstalled just fix the code and copy the new build of the custom action with super-duper exception handling over the existing file. When the installer is run again hopefully it won't notice the difference between files and this time the unhandled exception won't be unhandled.
If this isn't your problem then this post probably isn't very helpful
|
|
|
|
|
Hi Jimmanuel,
You identified my problem correctly. I will try what you reccomend.
Thank you,
choo_chu
|
|
|
|
|
Hi Jimmanuel,
Your solution worked! Thanks for your help
choo_chu
|
|
|
|
|
Glad to help
|
|
|
|
|
I've got several xml data access classes. Each is implemented as two partial class files. One generated by the XSD tool (one of the SDK commandline apps), it applies the attribute to each class it generates, and does not appear to have an option to stop it from doing so. The second is code that I've written that provides add/delete/validation type functions, these I'd like to be able to debug normally.
Deleting the attribute out of the autogenerated code manually is a poor solution since it would just come back each time the file was regenerated due to a schema change. I suppose I could find a tool that does an automated search/replace and call it from the batch file I use to regenerate the source files, but that strikes me as being more cumbersome than changing the code I wrote.
It is a truth universally acknowledged that a zombie in possession of brains must be in want of more brains.
-- Pride and Prejudice and Zombies
|
|
|
|
|
I don't think you can stop it, but you could inherit your class from the auto generated dataSet instead of using a partial. That way the debugger will step through the code in the inherited class just fine.
"An eye for an eye only ends up making the whole world blind"
|
|
|
|
|
I suppose that's an option, but not having to do that with generated code was listed as one of the benefits of partial classes when MS came up with the concept in 05.
It is a truth universally acknowledged that a zombie in possession of brains must be in want of more brains.
-- Pride and Prejudice and Zombies
|
|
|
|
|
I am developing an application in C#.NET , for transferring data between two PC's using RS232 protocol. For communication, i m using "SerialPort" class of "System.IO.Ports" namespace. but now i have a problems in recieveing the data and sending the data. even one major problem is whenever i'll recieve at that time i have to identify the begining of message and ending of message as well as if two messagees are recieveing at thae same time then how to differentiate that messagees. please help me i nthat. i really stuck in that. thank you in advance
Arpita Patel
|
|
|
|
|
Hi,
did you mention to use a start and a stop character, e.g. (char)1 start and (char)2 to stop.
Then use
recvStr = recvStr.Remove(0, recvStr.IndexOf((char)1)-1);
msg = recvStr.Substring(recvStr.IndexOf((char)1), recvStr.IndexOf((char)2, recvStr.IndexOf((char)1));
Kind regards
|
|
|
|
|
I used this code for sending the data
private void SendData()
{
if (CurrentDataMode == DataMode.Text)
{
// Send the user's text straight out the port
comport.Write(txtSendData.Text);
// Show in the terminal window the user's text
Log(LogMsgType.Outgoing, txtSendData.Text + "\n");
}
else
{
try
{
// Convert the user's string of hex digits (ex: B4 CA E2) to a byte array
byte[] data = HexStringToByteArray(txtSendData.Text);
// Send the binary data out the port
comport.Write(data, 0, data.Length);
// Show the hex digits on in the terminal window
Log(LogMsgType.Outgoing, ByteArrayToHexString(data) + "\n");
}
catch (FormatException)
{
// Inform the user if the hex string was not properly formatted
Log(LogMsgType.Error, "Not properly formatted hex string: " + txtSendData.Text + "\n");
}
}
txtSendData.SelectAll();
}
For the Recieving purpose I used
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// This method will be called when there is data waiting in the port's buffer
// Determain which mode (string or binary) the user is in
if (CurrentDataMode == DataMode.Text)
{
// Read all the data waiting in the buffer
string data = comport.ReadExisting();
// Display the text to the user in the terminal
Log(LogMsgType.Incoming, data);
}
else
{
// Obtain the number of bytes waiting in the port's buffer
int bytes = comport.BytesToRead;
// Create a byte array buffer to hold the incoming data
byte[] buffer = new byte[bytes];
// Read the data from the port and store it in our buffer
comport.Read(buffer, 0, bytes);
// Show the user the incoming data in hex format
Log(LogMsgType.Incoming, ByteArrayToHexString(buffer));
}
}
now give me appropriate answer for my question.
thanks a lot fro replying me.
Arpita Patel
|
|
|
|
|
To parse individual messages out of a stream of them there needs to be a start message flag that signals the beginning of a message. Just pick a unique character or pattern of characters and put that at the beginning of each message. Pick a different flag and put it at the end to identify where each message stops.
|
|
|
|
|
Hi,
if you can choose the protocol freely, then this would probably be the easiest set-up with reasonable reliability:
- send everything as text using ASCII, i.e. don't use binary data;
- end each message on a reserved character, \n is a good choice; you can achieve this by setting
SerialPort.NewLine to '\n' and using WriteLine()
- create a receiver thread, which basically is an eternal loop performing a ReadLine(); this one will block until a SerialPort.NewLine was received, then return all the data received so far, which would be exactly one message.
WARNING: the receiver thread cannot directly access any GUI Controls, it needs Control.Invoke for that.
Luc Pattyn [Forum Guidelines] [My Articles]
DISCLAIMER: this message may have been modified by others; it may no longer reflect what I intended, and may contain bad advice; use at your own risk and with extreme care.
|
|
|
|
|
I do a lot of RS232 programming for my job. All of our messages usually start with a special character, such as the <stx> hex 0x02 character, followed by a message identifier that we use to let the program know what to do with the message. Then the message is ASCII encoded text followed by a termination character, such as <etx> hex 0x03. When a message is received, the starting character, message identifier, and ending character are stripped from the message which is then passed to whatever part of the application it is intended for. If you are having trouble with receiving and sending data, make sure that you are using a crossover cable <null modem=""> which has the send and receive wires switched at one end of the cable. If you use a straight through cable then the receiving computer will not be getting the data on the receive pin but the transmit pin, which it won't process. By definition, serial communication means that you cannot get two messages at the same time as you are transmitting the bytes in a 'series'. So as long as you are looking for the stop character to terminate a message then the next message should not get jumbled or lost as long as you don't overrun the buffer.
|
|
|
|
|
thanks for replying me
hey you said you do lot of RS232 programming. can you teach me that because I am new in RS232 programming with multithreading and i have to do it in time so I dont have enough time but I will manage if you are ready to teach me.
I really appriciate for that.
I am waiting for your reply.
thanks.
|
|
|
|