|
Like T M Gray said already... Where are you actually getting an environment variable in this code?
And if that's your goal, why not just do it the easy way?
string something = Environment.GetEnvironmentVariable("something");
Not really sure what launching command-line processes and redirecting I/O has to do with environment variables...
|
|
|
|
|
Hi,
I tried that, and when I have a form that has a button/messagebox to check that and then display it, it keeps displaying the outdated variable value?
|
|
|
|
|
Because if you define a variable in another process, it won't exist in this one.
|
|
|
|
|
Hi,
I'm not setting it, it will change by the OS ... but when I call it after the change it still does not display the new value?
|
|
|
|
|
How are you checking the value?
I'm not sure if this changed in the latest versions of Windows, but usually environment variables are initialized with a copy of the OS environment variables when the process starts. While the process is running, any changes in environment variables via the OS would not be seen by the process and any changes made to variables in the process will not be passed back to the OS.
CQ de W5ALT
Walt Fair, Jr., P. E.
Comport Computing
Specializing in Technical Engineering Software
|
|
|
|
|
Hi Walt,
I've checked it both with the code above and by just calling the environment variable with a get environment variable call.
Both times the code will not reflect the change until I restart the application I am building.
I know the variable is changing though, because I can open a cmd prompt and type %sessionname% and it will reflect whether I am logged in locally or via console mode.
I tried to keep spawning a new cmd prompt window within a form, so that it would close and then reopen the window and write the %sessionname% value, but closing the cmd window seems to kill my do while loop and I couldn't get around that even after 3 hours of trial and error
|
|
|
|
|
Yes, that's what I would expect.
The environment variables in your process and the OS and any other process are meant to be totally independent so that total chaos in the OS won't ensue. When you spawn your process (cmd window, etc.) it starts with a copy of the owner's environment variables, but any changes it makes are local to your process (cmd window) and any changes made in another process (a new cmd window or the OS) will not be seen by your process. I think you have confirmed that that's exactly what is happening.
If you need to pass changeable information between processes, environment variables are not the solution. They are meant to be used for more or less static system information.
CQ de W5ALT
Walt Fair, Jr., P. E.
Comport Computing
Specializing in Technical Engineering Software
|
|
|
|
|
Hi Walt,
I thought it would load the environment variables in real time, not each time the program launches but that would explain my results.
What would you suggest to monitor sessionname status? I'd ultimately like to create a service that runs under the local system account and monitors what type of connection someone is logged in under, be it console or RTP. Any suggestions?
|
|
|
|
|
Well, I'm no expert on the topic of inter-process communications!
If everything is running on a single machine, I'd probably take the chicken way out and use a simple file to save information. But I suspect a true service would be much better and probably more scalable.
CQ de W5ALT
Walt Fair, Jr., P. E.
Comport Computing
Specializing in Technical Engineering Software
|
|
|
|
|
I'm not even sure how to ask the question, hah. I want two classes:
User:
public class User
{
private List<Group> groups = new List<Group>();
public List<Group> Groups
{
get { return groups; }
}
}
and Group:
public class Group
{
private List<User> users = new List<User>();
public List<User> Users
{
get { return users; }
}
}
Say I have a Group "All Users". When I initialize a User I assume I'm going to get an out-of-memory error.
Not that anyone would want to do this, but you should be able to do this:
User u = new User();
u.Groups["All Users"].Users[u.Username].Groups["All Users"].Users[u.Username] ;
If anyone could help I'd appreciate it.
|
|
|
|
|
Make your groups collection in User class a singleton. It should be instantiated and populated just once.
|
|
|
|
|
you could solve that by postponing the creation of a list till you need it, like so:
public class Group
{
private List users;
public List Users
{
get {
if (users==null) users=new List();
return users;
}
}
}
and optionally similar for user.
That way, you only get the list when you actually use it.
|
|
|
|
|
That's pretty good. 5.
------------------------------------
I will never again mention that I was the poster of the One Millionth Lounge Post, nor that it was complete drivel. Dalek Dave
CCC League Table Link
CCC Link[ ^]
|
|
|
|
|
Took me a minute to understand but I get it.
Thanks very much!
[EDIT] and a few minutes later it seems all too obvious and I get mad for not thinking of it.
|
|
|
|
|
While it is technically correct, it does prevent the infinite recursion, this is still not the right way to handle things.
1.
If you have a many-to-many relation like that, you should keep it outside both classes, i.e. the User class shouldn't automatically create or touch groups, and the Group class shouldn't create or touch users. You could give them a second constructor where a Group (or a User) is a parameter, basically saying "give me a new User and add him to this Group" for comfort, note this makes it all explicit.
2.
If you want a single list that contains all objects of some class, the best way to do it is with a static list burried inside the class; then you should add them automatically.
class User {
private static List<User> users=new List<User>();
public User() {
users.Add(this);
}
}
You may then add a property that gets a read-only copy of the list of users, so your app can look at it.
Warning: the list will grow; it will also remember User objects that no longer exist in your app, however by adding them to the list, they will never get collected. So you may want to use WeakReference instead; and maybe use a finalizer. etc.
|
|
|
|
|
In my opinion, a class shouldn't know anything about how, where, or whether it is stored anywhere -- that is not within its area of responsibility. Basically, a User may have a collection of Groups and a Group may have a collection of Users, but neither should be in charge of "getting" those collections. Some other class is responsible for knowing about the database and the relationship and reading and populating the collections.
Here's a little something I just worked up to show how I might do it -- though I probably wouldn't :
public sealed class UserGroupManager
{
public UserGroupManager
(
Test DataContext
)
{
this.Users = new System.Collections.Generic.HashSet<Test.User>() ;
this.Groups = new System.Collections.Generic.HashSet<Test.Group>() ;
foreach
(
Test.User user
in
DataContext.Users
)
{
foreach
(
Test.Group group
in
DataContext.ExecuteQuery<Test.Group>
(
@"SELECT [Group].* FROM UserGroup INNER JOIN [Group] ON UserGroup.GroupID=[Group].ID WHERE UserGroup.UserID=?"
,
user.ID
)
)
{
group.Users.Add ( user ) ;
user.Groups.Add ( group ) ;
this.Groups.Add ( group ) ;
}
this.Users.Add ( user ) ;
}
return ;
}
public readonly System.Collections.Generic.HashSet<Test.User> Users ;
public readonly System.Collections.Generic.HashSet<Test.Group> Groups ;
}
(I've only been fiddling with Linq-to-SQL for the last few days.)
|
|
|
|
|
From here http://www.codeproject.com/KB/threads/smartthreadpool.aspx#Feature1[^]
"It is also stated that the operations in the .NET ThreadPool should be quick to avoid suspension of the work of others who use the .NET ThreadPool. Note that several AppDomains in the same process share the same .NET ThreadPool. If you want a thread to work for a long period of time, then the .NET ThreadPool is not a good choice for you (unless you know what you are doing)."
My question is, why. Why dotnet ThreadPool is only for quick executions? This makes it kind of useless as if jobs are quick to execute you wouldn't really need to have it placed on a thread in the first place.
Also, what really are the negative consequences for putting long running jobs on dotnet ThreadPool's threads?
Thanks
dev
|
|
|
|
|
devvvy wrote: This makes it kind of useless as if jobs are quick to execute you wouldn't really need to have it placed on a thread in the first place.
Not really, you'd still save the time of creating a thread. Take below statement as an example;
this.Invoke(()=> this.Visible = false; ); Not a very nice example, I agree. The example-project that comes with the Msnp-sharp protocol uses this construction extensively, and it makes a nice reactive UI.
Quick is relative here, I'm using it for everything that takes more than half a second, and less than 3 seconds.
devvvy wrote: Also, what really are the negative consequences for putting long running jobs on dotnet ThreadPool's threads?
Running out of threads. Means that the next request will be blocked until there's a worker available.
I are Troll
|
|
|
|
|
Good answer, deserves a 5.
------------------------------------
I will never again mention that I was the poster of the One Millionth Lounge Post, nor that it was complete drivel. Dalek Dave
CCC League Table Link
CCC Link[ ^]
|
|
|
|
|
Thanks
|
|
|
|
|
devvvy wrote: My question is, why. Why dotnet ThreadPool is only for quick executions? This makes it kind of useless as if jobs are quick to execute you wouldn't really need to have it placed on a thread in the first place.
This seems counter-intuitive, I had to check what the article writer said for out myself. I hadn't heard this statement before but the answer (at least the one found) makes sense, to the point of being obvious. The ThreadPool has a limited number of threads available, which can recycle once a thread's process has finished. If your process is long-lived, the pool can more easily run out of threads to recycle, reducing performance.
So that leaves the question "Why bother with a ThreadPool at all?", the answer is that creating a Thread is an expensive process: if the process you are running is sort-lived compared to the creation of a new thread (and this is where the "short-lived" comes from) then creating a new thread is a bad choice. The correct choice (assuming you have no other requirements) in this case is to use a ThreadPool, the threads are recycled, reducing the overhead.
Sources:
http://htmlcoderhelper.com/when-to-use-thread-pool-in-c/[^]
http://blogs.msdn.com/b/pedram/archive/2007/08/05/dedicated-thread-or-a-threadpool-thread.aspx?wa=wsignin1.0[^]
Good question, and I've (in the best tradition of South Park) Learned something here today!
|
|
|
|
|
"So that leaves the question "Why bother with a ThreadPool at all?", the answer is that creating a Thread is an expensive process: if the process you are running is sort-lived compared to the creation of a new thread (and this is where the "short-lived" comes from) then creating a new thread is a bad choice. The correct choice (assuming you have no other requirements) in this case is to use a ThreadPool, the threads are recycled, reducing the overhead. "
Yes exactly, if it's short lived, I wouldn't even bother put on a thread. Or have say five to ten short lived operations all put on one Worker thread while UI thread sits around to entertain the users.
But I don't see why the notion of dotnet ThreadPool not meant for long running jobs
If ThreadPool is only for short small jabs, then - yes, creating separate Threads is expensive but you could have just created ONE thread for all/number of short jabs instead of multiple threads or using a ThreadPool at all. Precisely this makes dotnet ThreadPool quite useless if really it's not meant for long running jobs (especially if simple job cancels is not supported)
dev
|
|
|
|
|
"Long lived" is relative (and fuzzy!), and the dev needs to achieve a balance.
Here, you would need to balance off the number of threads created in the pool against their lifespan. At some point the process will be long-lived enough that the threadpool will run out of threads. But you are likely to notice performance problems before you get to this stage (especially in a UI). This problem is allieviated (as Pete's post described) by the fact that we can spin off a fairly large number of threads per pool. Luc's point is also a good one: if you have a few long-lived processes (or I suppose if you spin off new long-lived processes at a slow rate) then the thread pool is an option: the processes won't occupy enough threads to block the addition of all of them. The threadpool might be slightly less efficient than coding the threading yourself in this case, but the loss is small enough not to be a problem in most applications, but you get the benefit of *much* neater code.
In my experience, a suck it and see approach is best for this sort of stuff, if you are still confused, you could try writing a test rig to compare the relative performance of a ThreadPool with processes of differing lengths and addition rates, against managing your own threads.
[Edit 2]
I suggest you read Luc's response, and Pete's too. This doesn't seem to be that much of a problem any more. To be honest, I haven't found any issues with it in the past - but by the time I only really had to use ThreadPools in earnest we were on version 3.0 of the framework.
|
|
|
|
|
|
I use the SmartThreadPool object. I wrote an article that uses it to demonstrate thread pool usage, delegates, and events:
Multithreading, Delegates, and Custom Events[^]
.45 ACP - because shooting twice is just silly ----- "Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997 ----- "The staggering layers of obscenity in your statement make it a work of art on so many levels." - J. Jystad, 2001
|
|
|
|
|