|
In a recent thread on the ndoc development list (for which I contribute), we were talking about the documentation of static constructors and that got me to thinking:
In most of my work, I use the approach for creating singleton objects by makeing a private constructor, then having a static property that returns an instance from which I can call other public or internal methods or properties. The whole thing looks like this:
public class Test
{
private string text;
private static Test instance;
private static volatile object syncRoot = new Object();
private Test()
{
this.text = "Test";
}
public static Test Instance
{
get
{
if (instance == null)
lock (syncRoot)
if (instance == null)
instance = new Test();
return instance;
}
}
public string Text
{
get { return this.text; }
}
}
This seems to be the method that Microsoft uses in the .NET BCL. And it works good. I do use static constructors in some things that aren't so sensative (like wrapping some GetDevice Win32 API code).
What I'm wondering is if static constructors work just as good as the method above? I haven't been able to find any documentation that discusses this in any detail, but my first reaction is that the first method is better because monitors are used and if would be thread-safe. But does the CLR invoke static constructors in a thread-safe manner on its own?
Reminiscent of my younger years...
10 LOAD "SCISSORS"
20 RUN
|
|
|
|
|
acorrding to this article, the best way is thus:
sealed class Singleton
{
private Singleton() {}
public static readonly Singleton Instance = new Singleton();
}
as for your threading question: "What about thread-safe initialization? The Framework addresses this too. The Framework internally guarantees thread safety on static type initialization."
|
|
|
|
|
Essentially, this is the same as using a static constructor. All statics that are initialized are done so in the .cctor specialname (the static constructor). Using the above syntax is merely a shorthand. So, you've actually described the same process.
The first method I described and coded doesn't rely about a static constructor except for the synchronization object, which is only used by the Monitor and is not indicative of the singleton itself.
I appreciate your answer though. The latter part was good to know. I've always suspected based on evidence, but I've never been able to find it in the documentation which I've read from start to finish several times. (and, oh, how the ending makes me cry! :P)
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
|
I am making a photoshop-like toolbox, everything is fine except one probelm.
I have a form object as a childform of my main form.(after set the TopLevel property to false)
then the titlebar of the toolbox form would always be under the gray state?
So what's the matter with my implement?
thanks!
|
|
|
|
|
But in this realization, what if I need another form with the same demand?
I mean, I want several forms being activated at the same time(not the gray title).
The function works well without this requirement, but I just want it to act as the normal expectation.
|
|
|
|
|
What I exactly want is to show several forms as some 'toolboxes', and I don't want them to act like some dialogs that only one of them has its title bar highlighted at one point.And aslo these 'toolboxes' should act like the childs of the main form(constrained inside the bound of the main form and has a certain relative loocation in the main form).
Some child forms would do the second requirement, but the title bar thing cannot be satisfied.
|
|
|
|
|
Thanks for your reply and code
But it seems you haven't got my point...
in your realization form2 and form3 still cannot have both of their title bar highlighted at the same time.
I can set the form3.TopMost property to true and form2.TopMost property to false to bring form3 to the top level(title bar highlighted) and bring form2 drawn behind(gray title bar). That's all I can do now.
The photoshop toolbox and layer panel etc. are somekind of forms that work like 'always at top', even above the mainform.
|
|
|
|
|
thanks
Is it complex to use windows hooks to do the work?
Or only some invoke of win32 apis?
|
|
|
|
|
Has anyone ever seen an documentation/examples on building a stand alone webserver? I'm intersted in creating a FREE tiny webserver that will allow advanced webserver like functions but able to be run from a CD/DVD or Hard Drive. I know that it is possible becase there are a couple of products like this out there.
If anyone has any ideas please let me know. I could really use a sample program with code. Or at least information that will point me in the right direction.
Thanks,
Josh
|
|
|
|
|
There are several articles here on CP that deal with such issues, including reading from sockets, handling basic HTTP headers (which is relaly quite easy - it's what to do with some of them that gets difficult at times!), and serving pages. And, heck, since you're doing this in .NET, it wouldn't be hard to host ASP.NET pages. There's an entire namespace for this in .NET, and the classes are all there. There's really not much you have to do to provide basic services to ASP.NET pages (and controls, etc.).
One thing I would add (if you haven't already thought of it) is to effectively use caching, especially when run from a CD/DVD drive, as these things have very long latency times and very slow read times. It does sound like an interesting idea, though!
Reminiscent of my younger years...
10 LOAD "SCISSORS"
20 RUN
|
|
|
|
|
Here is a table of a lot of Run-Time routines and then their mappings into the .NET World...
Link[^]
Good for those of us who have to work in both...
-Nathan
---------------------------
Hmmm... what's a signature?
|
|
|
|
|
Yummy !
..Ctrl-P
..thanks !
FOR
|
|
|
|
|
Great link, thanks.
-Nick Parker
|
|
|
|
|
|
WiB wrote:
How to pass arguments in OnStart method of service?
Service supposed to start automatically at a boot time.
There is no way to pass arguments to a service at boot time, that is because the Windows API CreateService does not take any "default" argument. However, if you can create a service that is not started automatically at boot time and create a second service whose job is to start the first service at boot time, then you can pass arguments to the first service (using the StartService API).
<Edit>It is probably easier to</Edit> do it (the second service) in C/C++, by the way. If you don't want to bother writing a service in C/C++, you can use XYNTService[^] to start your service, passing any argument you want from the "command line" defined in the .ini file.
Click here to see my articles and software tools
|
|
|
|
|
WiB wrote:
If I have an .INI file with arguments I can read this .INI file in OnStart method of service and I don't need to create second service, do I?
Yes, if you are satisfied with reading data from a file, then you don't really need to pass any argument. The second service makes it possible to pass arguments through command line at boot time.
WiB wrote:
In C# there is ServiceController class that controls services. What's the problem to create second service in C#?
No problem, I should have said "it is probably easier to ..."
Click here to see my articles and software tools
|
|
|
|
|
WiB wrote:
If I start second service by calling StartService from first service, how do I pass arguments in service?
The StartService API can take arguments for the service to be started, if a service calls StartService to start another service, the arguments will be passed to the other service as if you have typed them from the command line. Of course, you have to get the arguments from within the first service. You don't need to do much when using a tool like XYNTService.
Here is how to use XYNTService to do what you need:
a) Copy XYNTService.exe to your local machine and install it with the following command:
<br />
XYNTService.exe -i<br />
b) Save the following text as file XYNTService.ini in the same folder:
<br />
[Settings]<br />
ProcCount = 1<br />
[Process0]<br />
CommandLine = c:\MyDir\XYNTService.exe -r MyService Arg1 Arg2 Arg3<br />
c) Reboot the machine.
When the machine is started, XYNTService will execute commands defined in the XYNTService.ini file, in this case, the command is
<br />
XYNTService.exe -r MyService Arg1 Arg2 Arg3<br />
The above command will call StartService passing Arg1, Arg2, and Arg3 to the service named MyService, MyService must not auto start at boot time. To stop your service from the command line, use the following
<br />
XYNTService.exe -k MyService<br />
Hope this helps.
Click here to see my articles and software tools
|
|
|
|
|
WiB wrote:
I took a look on your code.
For example, I create the service passing the following string as the lpBinaryPathName parameter of CreateService():
"d:\\foo\\foo.exe param1 param2"
I suppose that in main(int argc, char *argv[])
argc will be 2
argv[0] will be param1
argv[1] will be param2
Can you tell me if it's correct?
I don't think it will work that way. You will probably get a "file not found" or "invalid path" error. The lpBinaryPathName parameter does not contain arguments. Read my other reply on how to get around this.
Click here to see my articles and software tools
|
|
|
|
|
|
WiB wrote:
Yes, it's true, it works!
Ok, good for you! Just one more twist, if you pass the arguments at CreateService time, how do you change them later? You will have to call a service api (or use ServiceController class) to do that. Of course, you can always uninstall the service and reinstall it with different arguments.
<Edit>I still think using XYNTService is a better way, you don't even need to write your own service, you can do what you want in a regular and simpler program and start the program with XYNTService.</Edit>
Click here to see my articles and software tools
|
|
|
|
|
No, argc is 3 and argv[0] is actually the application name. argv[1] and argv[2] are param1 and param2, respectively. As a side note, .NET does not pass the application as the first argument. Some languages do, some languages don't.
Besides, parameters aren't passed to the Windows Service in the entry point (commonly referred to as main ). In .NET, these are passed in OnStart(string[] args) .
If I were you, just read settings from the app's config file (named MyServer.exe.config - just append ".config" to your service application and put them in the same directory). You could write your own IConfigurationSectionHandler , or just use the provided <appSettings> , which gives you a simple key-value pair. It's just an XML file so it's easy to edit (both manually and programmatically).
Reminiscent of my younger years...
10 LOAD "SCISSORS"
20 RUN
|
|
|
|
|
Parameters are not passed to Windows Services through Main ! Read the documentation - it states this clearly. They are passed from the SCM to .NET's virtual OnStart(string[] args) method. The main method is only the entry point for the executable. If you want to pass parameters to your service, you set these in the server control manager (the Services MMC snap-in, for example, allows you to do this).
Reminiscent of my younger years...
10 LOAD "SCISSORS"
20 RUN
|
|
|
|
|
But did the SCM pass the parameters, or did you when you executed the EXE? You're supposed to override OnStart . RTFD!
Reminiscent of my younger years...
10 LOAD "SCISSORS"
20 RUN
|
|
|
|
|
Parameters are not stored in the registry - registry keys are stored in the registry. Parameters and settings are not the same thing. Yes, you can - in Main - query the registry for settings, but parameters are passed TO main, and only the executable loader does that, beings that it's the entry point and not just a function (at least when the executable is loading).
There is nothing wrong with storing settings in the registry and reading them from the registry in Main, but it is recommended (RTFD!) to do everything in OnStart . This follows the .NET model of OOP since the entry point doesn't necessarily have to be in the ServiceBase -derived class. It could be anywhere. The SCM doesn't use the entry point at all - the executable loader does. The ServiceBase class is a wrapper of sorts that the SCM does - indirectly - use. This is the point I've been trying to make. You do know what RTFD means, right? It's all in there, both in the .NET documentation and a lot in the Platform SDK for Win32. You shouldn't rely on the entry point (Main in C#, for example).
So, read your settings from the registry or from the .NET config file (which is preferred over the registry for .NET applications for many reasons), or from a database or INI file - it doesn't matter! Just don't confuse parameters with settings and make sure you know how the SCM passes parameters.
Reminiscent of my younger years...
10 LOAD "SCISSORS"
20 RUN
|
|
|
|