I read values in from a file on startup of my application.
I'd like to use those values during a condition in a timer every xx seconds later in my program's execution.
I don't want to read the file again. How do I go about referencing the values initially read in?
The timer is in a completely different project/class to initial reading of the file.
Assign them somewhere!
If you're reading from the file and creating the timer condition in the same place, you could even use a local variable to store the values.
If they need to be accessed later but you don't want to recreate them, you could store them in a field in the class where this is happening.
If these values will be used elsewhere in your application, but will remain relevant as long as this class' type is around, you could store them in a static field or property.
If you want them to be loaded on-demand and then saved for subsequent access, you could use a Lazy<T> type to store them.
If you are needing to reference them from another class and hold them in memory - create a public static property somewhere to which you can assign the data.
public static MyDataType Data{ get;set;}
... where MyDataType is an object that holds your data. You can then test for Null in your timer method to make sure this has happened before continuing.
Related
Is there like a rule of thumb about when to go either over the other?
Im curious because i have a dilemma here, where i have a very frequently used method, return a custom class type that is rather large. Im wondering if it wouldnt be cheaper to hold an instance of this custom class in a field, and then in the method just change and return it every time, rather than creating a whole new object as would be the case if i had a new class instance created in the method every time.
The main difference between returning a newly created instance of a class and returning a field is enormous: in the latter case, the instance is shared because all clients receive a pointer to the same instance. That means: whenever any of the clients (or the original creator of the instance) changes something in the instance, all clients will now see all those changes. In the former case, all instances are different, and changes affect only the current client.
So take a really close look at the requirements and find out which of the behaviors is required. Getting them wrong can have devastating effects.
What you seem to ask for is a so called lazy field. You declare it as System.Lazy<> like so
private System.Lazy<YourClass> mYourClassInstance;
...
mYourClassInstance = new System.Lazy<YourClass>(() => new YourClass());
and then you can get the instance via
mYourClassInstance.Value
anywhere you want but the value (instance) is only created once.
In my WCF code, user's id and name are stored in static variables. It is retrieved from HttpContext.Current.User.Identity.Name and a database hit. Also there are other static variables to store connection string, log file related stuff etc.
Recently i found myself in a race condition where a second call from my client set the user name when the first call was still processing. This resulted in first call reading user data updated by the second call.
To avoid this, I read about InstanceContextMode.PerCall and how it makes static variables behave like non-static for every call.
My questions are
1) If i use InstanceContextMode.PerCall, does that mean it will instantiate all static variables and methods? I am planning to use this only to get new user data for every call. However, I assume this will also make a new instance for connection string static variable, log file and other static variables. Is this correct? Will it affect performance (reading again from web.config etc)?
2) Is there a way to use InstanceContextMode.PerCall but to create instance only for user data related static variables and leave the connection string related static variables?
3) Is a dispose method ( implementing IDispose) mandatory to dispose off the static variables once the call is done?
First of all not sure why you have all those data in a static variable? that looks like a bad design. When you say InstanceContextMode.PerCall; to my understanding every call have a separate copy of the data and it's unique per call.
If you want your data to be not modified then try declaring them as static readonly instead. Lastly, you should opt for a better design rather.
I am writing a program which will manipulate certain objects, let's call them "Words". Each word is an instance of one of several classes. There can be lots and lots of these at a time.
Each of these Word objects needs access to a dictionary, stored in an XML file. I don't feel like each Word object should be loading the XML file separately. The Word objects should be able to access some global pool of program data.
What's the best way to deal with this? Should I have a class called ProgramData which contains the XML document and gets passed to every Word object when they are created? This won't cause multiple instances of the XML file to be loaded into memory, will it? Can I do what I want to do without passing ProgramData to every new object?
You should load the XML file into one instance of ProgramData, and then pass that instance into each Word instance (maybe in the constructor). You could also make a static property in the Word class that you set before you start instantiating Words, but be sure to use locking for thread safety.
Your alternative is the Singleton pattern, but trust me, you don't want to go down that road.
Edit: Just to be clearer, this is the first option (the one I'd use):
public class Word
{
private ProgramData _Data
public Word(ProgramData data)
{
_Data = data;
}
public void MethodThatUsesData
{
// _Data.TryGetValue()
}
}
// in your main method or initialization routine:
ProgramData data = MethodThatLoadsData();
Word w = new Word(data);
Your ProgramData class can have a static variable for the XmlDocument and thus you won't have to pass the variable through a constructor; your other class can just reference ProgramData.YourVariable.
To answer your other question, no, this approach will not cause multiple instances of the XML file to be loaded into memory, and nor will drharris's approach.
Also, keep in mind that this information applies to all object oriented programming languages (at least those that I'm aware of), not just C#. If you load the XML document into memory once in a method called myMethod(), and myMethod() is only called once... guess what, that XML document will only get loaded into memory once. Only things that you coded to happen, or that another dev coded (and you called either directly or indirectly) will happen. There is no magic.
From the MSDN documentation for the FileInfo.Name property, I see that the data for the property is cached the first time it is called and will only be updated subsequently by using the Refresh method.
I've the following questions which I can't find or aren't too clear in the documentation:
Is the data for all properties cached at the same time?
Is the Refresh method called on creation of the FileInfo, or only when a property is called for the first time?
If I've called one property, e.g. the Name property, and it's called Refresh, will calling a different property, e.g. the DirectoryName property, for the first time cause it to call Refresh again, or is it only called by the first property accessed in the entire class (see question #1)?
Can I pre-cache all the properties by calling Refresh manually? (Assuming it's not pre-cached on construction of the object)
Does calling Refresh manually cause properties which are pre-cached, e.g. CreationTime, to be refreshed as well?
At a guess, yes. It seems like a bit of a self-defeating "optimisation" for FileInfo to fetch only the properties you've fetched before, especially when they can be (and probably are) all fetched in one API call.
The fact that the documentation calls out DirectoryInfo methods which serve up already-cached FileInfos suggests quite strongly (to me, anyway) that simply constructing a FileInfo doesn't cache anything. It makes sense - if you construct a FileInfo directly, it might refer to a file that doesn't exist yet (you plan to create it, for instance), whereas all the methods which return cached FileInfos refer to files that exist at the time of the snapshot, under the assumption you're going to use at least some of them.
No, by my answer to question 1. That's why the Refresh method is there.
I would imagine so (see answer 1).
Yes. See answer 3.
The value of the CreationTime property is pre-cached if the current
instance of the FileSystemInfo object was returned from any of the
following DirectoryInfo methods:
GetDirectories
GetFiles
GetFileSystemInfos
EnumerateDirectories
EnumerateFiles
EnumerateFileSystemInfos
To get the latest value, call the Refresh method.
If the file described in the FileSystemInfo object does not exist,
this property will return 12:00 midnight, January 1, 1601 A.D. (C.E.)
Coordinated Universal Time (UTC), adjusted to local time.
NTFS-formatted drives may cache file meta-info, such as file creation
time, for a short period of time. This process is known as file
tunneling. As a result, it may be necessary to explicitly set the
creation time of a file if you are overwriting or replacing an
existing file.
(MSDN)
Internally, Refresh calls the standard Win32API and thus fills all properties.
[...]
flag2 = Win32Native.GetFileAttributesEx(path, 0, ref data);
Accessing any property that is specified to Refresh causes a full refresh, for instance:
public DateTime LastAccessTimeUtc
{
[SecuritySafeCritical]
get
{
if (this._dataInitialised == -1)
{
this._data = default(Win32Native.WIN32_FILE_ATTRIBUTE_DATA);
this.Refresh();
}
[...]
I have an abstract class which runs a fairly computationally intensive series of static functions inside several nested loops.
In a small number of these loops, I need to obtain a list of dates which are stored in a comma-separated string in a .settings file. I then parse them into DateTimes and use them.
The issue is, I'm re-parsing these strings over and over again, and this is using up quite a bit of CPU time (obviously). Profiling shows that 20% of the core algorithm is wasted on these operations. If I could somehow cache these in a place accessible by the static functions then it would save me a lot of processing time.
The simplest option would be to parse the list of DateTimes at the very start of computation, and then pass that list to each of the sub-functions. This would certainly cut down on CPU work, but it would mean that the sub-functions would need to accept this list when called outside the core algorithm. It doesn't make intuitive sense why a list of DateTimes would be needed when calling one of the parent static functions.
Another thing to fix it would be to make the class not abstract, and the functions non-static, and store the list of dates, etc, in variables for each of the functions to access. The reason I wanted to have it abstract with static functions is because I didn't want to have to instantiate the class every time I wanted to manually call one of the sub-functions.
Ideally, what I would like to do is to parse the list once and store it somewhere in memory. Then, when I do a subsequent iteration, I can somehow check to see if it's not null, then I can use it. If it's null (probably because I'm in the first iteration), then I know I need to parse it.
I was thinking I could have a .settings file which has the list in it. I would never save the settings file to disk, but it would basically allow for storage between static calls.
I know this is all very messy - I'm just trying to avoid re-writing a thousand lines of static code if feasible.
If you all think it's a terrible idea then I will raise my white flag and re-write it all.
If the dates are read-only then it's pretty straightforward - declare a static property on a class which loads the values if they don't exist and stores them in a static variable - something like this:
public class DateList
{
private static List<DateTime> mydates = null; // new List<DateTime>(); haha, oops
public static List<DateTime> Current {
get {
if(mydates == null)
{
lock(typeof(DateList)) {
if(mydates == null) {
mydates = LoadDates();
}
}
}
return mydates;
}
}
// thanks to Porges - if you're using .NET 4 then this is cleaner and achieves the same result:
private static Lazy<List<DateTime>> mydates2 = new Lazy<List<DateTime>>(() => LoadDates(), true);
public static List<DateTime> Current2
{
return mydates2.Value;
}
}
this example would then be accessed using:
var dates = DateList.Current
Be careful if the dates are not read-only - then you'll have to consider things in more detail.
Another thing to fix it would be to make the class not abstract, and the functions non-static, and store the list of dates, etc, in variables for each of the functions to access. The reason I wanted to have it abstract with static functions is because I didn't want to have to instantiate the class every time I wanted to manually call one of the sub-functions.
Do this. Classes exist in order to encapsulate state. If you store the cache somewhere static, you'll only make trouble for yourself if/when you want to add parallelism, or refactor code.
I'm not sure what you mean by the second part ("manually call"). Do you mean while testing?