Question about instances and Dictionary of Objects in C# - c#

Hello I've built a simple packet skeleton where each packet is a class file which extends a interface but whatever that's not important just a little intro to show you how it works and what i'm attempting to do.
say it's something like this
public static void HandlePacket(Player player, Packet p)
{
PacketHandler handler = null;
if(handlers.TryGetValue(p.getId(), out handler)) {
handler.handlePacket(player, p);
} else {
Console.WriteLine("Unhandled packet: " + p + ".");
}
}
But okay the code above is a bit unrelated to this question.. my question has to do with filling up the handlers in the most efficient way.
handlers pretty much is just
private static Dictionary<int, PacketHandler> handlers = new Dictionary<int, PacketHandler>();
Now I cannot decide which way to populate the handlers map.
First way which is ugly goes something like this.
PacketHandler temp;
temp = new TalkPacket();
handlers.Add(33, temp);
handlers.Add(66, temp);
handlers.Add(22, temp);
handlers.Add(11, temp);
the elegant way looks like this.
handlers.Add(33, new TalkPacket());
handlers.Add(66, new TalkPacket());
handlers.Add(22, new TalkPacket());
handlers.Add(11, new TalkPacket());
My question is about the references why create more objects.. when you can re-use them.
So really I'm unsure does the ugly way only make one instance of TalkPacket object or 4? like the elegant way, if there is no difference with the code above. Then I might as well go with the elegant way.
I only will be including no more then 255 packets anyways so 255 objects big deal.. but most of the packets will be shared with other opcodes which is why I keep thinking why initiate more instances when they do the same thing.
At first i was looking for a way to bind multiple int datatypes to one object and having easy access like the TryGetValue command.
Anyways if anyone has any good suggestions let me know. Thanks.

The first way there is only one instance of TalkPacket created and all the 4 entries in the Dictionary reference this single instance.
In the second one, there are 4 different objects of type TalkPacket.
So no, these two are not equivalent.

You don't need a dictionary for this:
on the dictionary where you do:
PacketHandler temp;
temp = new TalkPacket();
handlers.Add(33, temp);
handlers.Add(66, temp);
handlers.Add(22, temp);
handlers.Add(11, temp);
is the same as:
private static PacketHandler handler = new TalkPacket();
public static void HandlePacket(Player player, Packet p)
{
PacketHandler handler = null;
if(idList.Contains(p.Id)) { // no need for dictionary, just array or list of int
handler.handlePacket(player, p);
} else {
Console.WriteLine("Unhandled packet: " + p + ".");
}
}
While the second method you proposed is the same as:
public static void HandlePacket(Player player, Packet p)
{
PacketHandler handler = null;
if(idList.Contains(p.Id)) { // no need for dictionary, just array or list of int
handler = new TalkPacket();
handler.HandlePacket(player, p);
} else {
Console.WriteLine("Unhandled packet: " + p + ".");
}
}
The second approach is slower.

Related

how do i get a class name variable

Im trying to get the class variable name
static void Main()
{
TaskAction m_first = new TaskAction();
m_first.Increment();
m_first.Increment();
TaskAction m_Second = new TaskAction();
m_Second.Increment();
}
public class TaskAction
{
private int m_Current;
public TaskAction()
{
m_Current = 0;
}
public void Increment()
{
m_Current++;
write(" TaskAction " + vairableName + " " + m_Current);
}
}
i want to it to write out:
TaskAction m_first 1
TaskAction m_first 2
TaskAction m_second 1
Retrieving metadata about your program like that is both complex and unnecessary, just add the name by passing it to the constructor.
static void Main()
{
TaskAction m_first = new TaskAction("m_first");
m_first.Increment();
m_first.Increment();
TaskAction m_Second = new TaskAction("m_Second");
m_Second.Increment();
}
public class TaskAction
{
private int m_Current;
private string m_taskName;
public TaskAction(string taskName)
{
m_taskName = taskName;
m_Current = 0;
}
public void Increment()
{
m_Current++;
write(" TaskAction " + m_taskName + " " + m_Current);
}
}
Short Answer: You can't.
Long Answer:
Technically, it's possible to determine a variable name by inspecting the IL (the intermidate language created by the C# compiler), but this operation is hard and error-prone. Also, you ignore some important questions:
First of all, as already asked here: Why? how such thing will enhance your program?
Each instance of the class can have multiple variables pointing to it (see my answer about types in .NET here). Which of them you want to get? For example, consider the following program:
var v1 = new TaskAction();
var c2 = new TaskAction();
c1.Increment(); // 1 c1
c2 = c1;
c2.Increment(); // 2 c1? 2 c2? 2 c1 c2?
By doing so, you break the encapsulation in a difficult way - any reflection breaks the encapsulation, and really don't use it unless you really need it - but so much? Reflection breaks the hidden information about the private interface, you question breaks the internal interface!
Since you didn't give enough information, I can't know why you tought you need that. But here is some solutions:
If you want, for example, logging with categories - simply pass the category to the constructor, as sugegsted above.
If you want to know which type the variable is - using its name is very very very bad approach, even though you have conventions - use polymorphism instead (best), or, at least, check the type with is/as, for example:
if (this is Drived)
{
((Drived)this).SomeDrivedMethod();
}
Note that it breaks the OOP principles: a class shouldn't know about its drived classes.
Hope this helped you. Have a nice day!
Edit:
For your purpose, you can do one of the following:
Best - debug your code, see the call stack etc.
Worse - print the caller method name, instead of the object name. It's can be done using System.Runtime.CompilerServices.CallerMemberNameAttribute:
void Increment([System.Runtime.CompilerServices.CallerMemberName] string caller = null)
{
// Default value to `caller` is neccessary
// ...
Console.WriteLine("Caller: {0}", caller);
}
Note: the compiler fills the caller parameter, not in runtime.
Get object.GetHashCode() if you want to uniquely identify class object or provide name to class by using custom constructor.

Why is a List<Session> getting additional sessions from a later run

I am using fiddlercore to capture session information to run a compare on the data in a particular response. One of the things I am noticing that I don't understand is that I am getting session information from the second environment into the List collection I have for the first.
public class ManageCompares
{
public static string _test2BaseURL = "https://test2/";
public static string _dev1BaseURL = "http://dev1/";
private void RunCompares(string email, string handler, Reporting report)
{
ManageProcess.ShutDownProcess("iexplore");
RunExports exportTest2 = new RunExports();
RunExports exportDev1 = new RunExports();
string password = "d";
List<Session> oAllSessions_Test2 = exportTest2.RunExportGeneration
(email, password, _test2BaseURL, handler);
ManageProcess.ShutDownProcess("iexplore");
List<Session> oAllSessions_Dev1 = exportDev1.RunExportGeneration
(email, password, _dev1BaseURL, handler);
exportTest2.ExtractResponse(oAllSessions_Test2, handler, report);
//report.SetEnvironment2Body(ManageExports.ExtractResponse
// (oAllSessions_Dev1, handler, report, report.Environment2));
if (report.Test2ResponseCode != 500 && report.Dev1ResponseCode != 500)
{
bool matches = CompareExports.CompareExportResults
(report.Environment1Body, report.Environment2Body);
if (matches)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Exports matched");
Console.ResetColor();
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Export does not match");
Console.ResetColor();
report.GenerateReportFiles();
}
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine
("A exception was returned. Please review the log file.");
Console.ResetColor();
}
}
}
public class RunExports
{
public List<Session> RunExportGeneration
(string email, string password, string baseUrl,
string handlersUrlwithParams)
{
IWebDriver driver = new InternetExplorerDriver();
FiddlerApplication.Startup(8877, FiddlerCoreStartupFlags.Default);
List<Session> oAllSessions = new List<Session>();
LoginPage login = new LoginPage(driver);
FiddlerApplication.AfterSessionComplete += delegate(Session oS)
{
Monitor.Enter(oAllSessions);
oAllSessions.Add(oS);
Monitor.Exit(oAllSessions);
};
try
{
driver.Navigate().GoToUrl(baseUrl);
login.LoginToView(email, password);
driver.Navigate().GoToUrl(baseUrl + handlersUrlwithParams);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
FiddlerApplication.Shutdown();
driver.Quit();
}
return oAllSessions;
}
}
List oAllSessions_Test2 and List oAllSessions_Dev1 are my two collections. When I debug the capture I typically see 15 rows in the oAllSessions_Test2 collection. Then after capturing oAllSessions_Dev1 I see the count has jumped up 14 or 15 and when I look at what is contained by the colleciton some of the Dev1 captures are now in there. oAllSessions_Dev1 has just the sessions I am expecting. I am guessing there must be a pointer someplace I am not expecting but I am stumped at this point how to clear it up. The other thing that I am noticing is that the session counter continues to increment while the application is cycling through the various cases.
I am also using Selenium WebDriver and IE to initiate the browser session but I don't think that is particularly relevant to this particular issue.
So what am I missing here?
Do this :
SessionStateHandler tAction = oS =>
{
Monitor.Enter(oAllSessions);
oAllSessions.Add(oS);
Monitor.Exit(oAllSessions);
};
FiddlerApplication.AfterSessionComplete += tAction;
......
//at the end before your return statement:
FiddlerApplication.AfterSessionComplete -= tAction;
So here is what's going on.
this: FiddlerApplication.Startup(8877, FiddlerCoreStartupFlags.Default);
(this specifically) FiddlerApplication
is holding onto references in an external application (fiddler) and administrating them for you. When you += and add a delegate FiddlerApplication.AfterSessionComplete += tAction;, the fiddler application was adding this to the list of methods it calls when the AfterSession event fires.
Because it's singleton (You are only dealing with one Fiddler application instance in your code), every time you do a += it adds it to the same list. This list in the FiddlerApplication doesn't get recreated every time you call your method. It's the same one that you called the first time, so even though your delegate falls out of it's scope declaration space (like local objects normally do in a method), the FiddlerApplication EventList maintains a reference to it and fires that delegate each time (and every other one).
So.....
In your method you create List<Session> oAllSessions = new List<Session>(); and access it in your delegate. This local variable is now passed back to the calling method, List<Session> oAllSessions_Test2 = exportTest2.RunExportGeneration.... and the delegate FiddlerApplication calls is the exact same list. So each time you call that method and the AfterSessionComplete fires, it updates the list even after it's been returned to the calling function.
To stop it you have to add: FiddlerApplication.AfterSessionComplete -= tAction; which tells the system "Hey, don't push updates to this method anymore. It's done receiving notifications."
In .NET languages class objects are passed by reference in almost all cases. If you assign an object reference to a variable, that variable will still refer to the original object. Changes to the original will be visible through all references. This is similar to how things used to happen in C/C++ when you stored pointers or references to structures in memory. The implementation details are different, but the results are the same.
Here's an example of what happens when you store list instances that might be changed later:
class ListTest
{
List<string> l = new List<string>();
public List<string> GetList() { return l; }
public void Add(string v) { l.Add(v); }
}
class Program
{
static void Main(string[] args)
{
ListTest t = new ListTest();
t.Add("a"); t.Add("b"); t.Add("c"); t.Add("d");
List<string> x1 = t.GetList();
List<string> x2 = t.GetList().ToList();
t.Add("e"); t.Add("f"); t.Add("g"); t.Add("h");
List<string> y1 = t.GetList();
List<string> y2 = t.GetList().ToList();
Console.WriteLine("{0}, {1}", x1.Count, y1.Count);
Console.WriteLine("{0}", string.Join(", ", x1));
Console.WriteLine("{0}", string.Join(", ", y1));
Console.WriteLine();
Console.WriteLine("{0}, {1}", x2.Count, y2.Count);
Console.WriteLine("{0}", string.Join(", ", x2));
Console.WriteLine("{0}", string.Join(", ", y2));
}
}
When you run that you get one set of identical results, because x1 and y1 are references to the same object. The second set of results are different because the call to ToList creates a new List<string> instance to hold the results.
This might be what is happening with the list that is returned by your Fiddler code.
--
Update after code review
What it looks like is that the delegate you're assigning to the AfterSessionComplete event is causing the code to treat oAllSessions as a static object bound to the event handler delegate. Various side-effects like this happen when you start playing around with code that generates closures and so on.
I would suggest changing the code to use a class method rather than an inline method - shift your oAllSessions variable and the code you're assigning to AfterSessionComplete out into the body of the class. That will at least establish whether the inline delegate is the cause of the problem.

Trying to set up delegates and handlers to call dynamically by using operation key only

I'm struggling with this new to me Delegates + Handlers thing.
It seems the right solution for me, but I can't tie everything up.
Will try my best to explain what I want to achieve.
First of all, I'm using .NET 4.0 Framework + Photon Server (For multiplayer games)
(There's no need in Photon experience in order to answer me)
So actually, what happens right now, is that the client (a game) sends operation to my server, which I must recognize and call a certain function on my server according to the operation code that I receive.
Here's how it looks right now:
switch (operationRequest.OperationCode)
{
case 1:
if (operationRequest.Parameters.ContainsKey(1))
{
Log.Debug("Received: " + operationRequest.Parameters[1]);
OperationResponse response = new OperationResponse(operationRequest.OperationCode);
response.Parameters = new Dictionary<byte, object> {{1, "Response Received"}};
SendOperationResponse(response, sendParameters);
Flush();
}
break;
}
This actually works fine for me. But, I know for sure there will be like 200+ operation codes.
Not really nice to switch all of them, It's better to call a function (handler) that is assigned to that Operation Code.
According to my knowledge, here where delegate comes handy.
I want to have a Dictonary, that stores "byte,Handler"
where "byte" is operation code
where "Handler" is a delegate to the function
Something like that I assume:
byte operationCode = operationRequest.OperationCode;
if(dictionary.ContainsKey((operaionCode)) {
dictionary[operationCode](someArguments);
}
From this point, I'm totally confused.
How to create such Dictionary, how to create handlers, assuming that I want to store them in different classes, how to delegate them and store in a dictionary.
Here's what my friend suggested me (and then vanished for one week, so I can't ask him again):
Create a dictionary
Dictionary<byte, name> = new Dictionary<byte, name>();
Add handlers to that dictionary
dict.Add(operationCode, MoveUnit);
Initialize delegates (Where!?)
???
Define your handlers
private void MoveUnit(SendParameters sendParameter) {...}
If.. anyone, by any chance, got the idea, please assist me.
Thanks to everyone for time spent on reading this. :|
Assuming all the methods take a SendParameters, then you really want:
private static readonly Dictionary<int, Action<SendParameters>> Actions =
new Dictionary<int, Action<SendParameters>>
{
{ 1, MoveUnit },
{ 2, AttackUnit }
};
...
static void HandleRequest(Request request)
{
Action<SendParameters> action;
if (Actions.TryGetValue(request.OperationCode, out action))
{
action(request.Parameters);
}
}
static void MoveUnit(SendParameters parameters)
{
}
static void AttackUnit(SendParameters parameters)
{
}
It gets slightly trickier for instance methods - the static dictionary doesn't know about instances, so it may make sense to make the action take the instance. Assuming this in a class called Foo, you might want something like:
private static readonly Dictionary<int, Action<Foo, SendParameters>> Actions =
new Dictionary<int, Action<Foo, SendParameters>>
{
{ 1, (foo, parameters) => foo.MoveUnit(parameters) },
{ 2, (foo, parameters) => foo.AttackUnit(parameters) }
};
private void MoveUnit(SendParameters parameters)
{
}
It's a bit uglier, admittedly... you really want to be able to build delegates which implicitly take "this" as the first parameter. There are ways of doing that, but they're a bit more complicated.

Best data structure for thread-safe list of subscriptions?

I am trying to build a subscription list. Let's take the example:
list of Publishers, each having a list of Magazines, each having a list of subscribers
Publishers --> Magazines --> Subscribers
Makes sense to use of a Dictionary within a Dictionary within a Dictionary in C#. Is it possible to do this without locking the entire structure when adding/removing a subscriber without race conditions?
Also the code gets messy very quickly in C# which makes me think I am not going down the right path. Is there an easier way to do this? Here are the constructor and subscribe method:
Note: The code uses Source, Type, Subscriber instead of the names above
Source ---> Type ---> Subscriber
public class SubscriptionCollection<SourceT, TypeT, SubscriberT>
{
// Race conditions here I'm sure! Not locking anything yet but should revisit at some point
ConcurrentDictionary<SourceT, ConcurrentDictionary<TypeT, ConcurrentDictionary<SubscriberT, SubscriptionInfo>>> SourceTypeSubs;
public SubscriptionCollection()
{
SourceTypeSubs = new ConcurrentDictionary<SourceT, ConcurrentDictionary<TypeT, ConcurrentDictionary<SubscriberT, SubscriptionInfo>>>();
}
public void Subscribe(SourceT sourceT, TypeT typeT, SubscriberT subT) {
ConcurrentDictionary<TypeT, ConcurrentDictionary<SubscriberT, SubscriptionInfo>> typesANDsubs;
if (SourceTypeSubs.TryGetValue(sourceT, out typesANDsubs))
{
ConcurrentDictionary<SubscriberT, SubscriptionInfo> subs;
if (typesANDsubs.TryGetValue(typeT, out subs))
{
SubscriptionInfo subInfo;
if (subs.TryGetValue(subT, out subInfo))
{
// Subscription already exists - do nothing
}
else
{
subs.TryAdd(subT, new SubscriptionInfo());
}
}
else
{
// This type does not exist - first add type, then subscription
var newType = new ConcurrentDictionary<SubscriberT, SubscriptionInfo>();
newType.TryAdd(subT, new SubscriptionInfo());
typesANDsubs.TryAdd(typeT, newType);
}
}
else
{
// this source does not exist - first add source, then type, then subscriptions
var newSource = new ConcurrentDictionary<TypeT, ConcurrentDictionary<SubscriberT, SubscriptionInfo>>();
var newType = new ConcurrentDictionary<SubscriberT, SubscriptionInfo>();
newType.TryAdd(subT, new SubscriptionInfo());
newSource.TryAdd(typeT, newType);
SourceTypeSubs.TryAdd(sourceT, newSource);
};
}
If you use ConcurrentDictionary, like you already do, you don't need locking, that's already taken care of.
But you still have to think about race conditions and how to deal with them. Fortunately, ConcurrentDictionary gives you exactly what you need. For example, if you have two threads, that both try to subscribe to source that doesn't exist yet at the same time, only one of them will succeed. But that's why TryAdd() returns whether the addition was successful. You can't just ignore its return value. If it returns false, you know some other thread already added that source, so you can retrieve the dictionary now.
Another option is to use the GetOrAdd() method. It retrieves already existing value, and creates it if it doesn't exist yet.
I would rewrite your code like this (and make it much simpler along the way):
public void Subscribe(SourceT sourceT, TypeT typeT, SubscriberT subT)
{
var typesAndSubs = SourceTypeSubs.GetOrAdd(sourceT,
_ => new ConcurrentDictionary<TypeT, ConcurrentDictionary<SubscriberT, SubscriptionInfo>>());
var subs = typesAndSubs.GetOrAdd(typeT,
_ => new ConcurrentDictionary<SubscriberT, SubscriptionInfo>());
subs.GetOrAdd(subT, _ => new SubscriptionInfo());
}

Large static arrays are slowing down class load, need a better/faster lookup method

I have a class with a couple static arrays:
an int[] with 17,720 elements
a string[] with 17,720 elements
I noticed when I first access this class it takes almost 2 seconds to initialize, which causes a pause in the GUI that's accessing it.
Specifically, it's a lookup for Unicode character names. The first array is an index into the second array.
static readonly int[] NAME_INDEX = {
0x0000, 0x0001, 0x0005, 0x002C, 0x003B, ...
static readonly string[] NAMES = {
"Exclamation Mark", "Digit Three", "Semicolon", "Question Mark", ...
The following code is how the arrays are used (given a character code). [Note: This code isn't a performance problem]
int nameIndex = Array.BinarySearch<int>(NAME_INDEX, code);
if (nameIndex > 0)
{
return NAMES[nameIndex];
}
I guess I'm looking at other options on how to structure the data so that 1) The class is quickly loaded, and 2) I can quickly get the "name" for a given character code.
Should I not be storing all these thousands of elements in static arrays?
Update
Thanks for all the suggestions. I've tested out a Dictionary approach and the performance of adding all the entries seems to be really poor.
Here is some code with the Unicode data to test out Arrays vs Dictionaries
http://drop.io/fontspace/asset/fontspace-unicodesupport-zip
Solution Update
I tested out my original dual arrays (which are faster than both dictionary options) with a background thread to initialize and that helped performance a bit.
However, the real surprise is how well the binary files in resource streams works. It is the fastest solution discussed in this thread. Thanks everyone for your answers!
So a couple of observations. Binary Search is only going to work if your array is sorted, and from your above code snippet, it doesn't look to be sorted.
Since your primary goal is to find a specific name, your code is begging for a hash table. I would suggest using a Dictionary, it will give you O(1) (on average) lookup, without much more overhead than just having the arrays.
As for the load time, I agree with Andrey that the best way is going to be by using a separate thread. You are going to have some initialization overhead when using the amount of data you are using. Normal practice with GUIs is to use a separate thread for these activites so you don't lock up the UI.
First
A Dictionary<int, string> is going to perform far better than your duelling arrays will. Putting aside how this data gets into the arrays/Dictionary (hardcoded vs. read in from another location, like a resource file), this is still a better and more intuitive storage mechanism
Second
As others have suggested, do your loading in another thread. I'd use a helper function to help you deal with this. You could use an approach like this:
public class YourClass
{
private static Dictionary<int, string> characterLookup;
private static ManualResetEvent lookupCreated;
static YourClass()
{
lookupCreated = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(LoadLookup);
}
static void LoadLookup(object garbage)
{
// add your pairs by calling characterLookup.Add(...)
lookupCreated.Set();
}
public static string GetDescription(int code)
{
if (lookupCreated != null)
{
lookupCreated.WaitOne();
lookupCreated.Close();
lookupCreated = null;
}
string output;
if(!characterLookup.TryGetValue(code, out output)) output = null;
return output;
}
}
In your code, call GetDescription in order to translate your integer into the corresponding string. If the UI doesn't call this until later, then you should see a marked decrease in startup time. To be safe, though, I've included a ManualResetEvent that will cause any calls to GetDescription to block until the dictionary has been fully loaded.
"Should I not be storing all these thousands of elements in static arrays?"
A much better way would be to store your data as binary stream in resources in the assembly and then load from the resources. Will be some more programming overhead but therefore doesn't need any object initialization.
Basic idea would be (no real code):
// Load data (two streams):
indices = ResourceManager.GetStream ("indexData");
strings = ResourceManager.GetStream ("stringData");
// Retrieving an entry:
stringIndex = indices.GetIndexAtPosition (char);
string = strings.GetStringFromPosition (stringIndex);
If you want a really good solution (for even some more work) look into using memmapped data files.
Initialize your arrays in separate thread that will not lock the UI
http://msdn.microsoft.com/en-us/library/hz49h034.aspx
if you store the arrays in a file you could do a lazy load
public class Class1
{
const int CountOfEntries = 17700; //or what ever the count is
IEnumerable<KeyValuePair<int, string>> load()
{
using (var reader = File.OpenText("somefile"))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var pair = line.Split(',');
yield return new KeyValuePair<int, string>(int.Parse(pair[0]), pair[1]);
}
}
}
private static Dictionary<int, string> _lookup = new Dictionary<int, string>();
private static IEnumerator<KeyValuePair<int, string>> _loader = null;
private string LookUp(int index)
{
if (_lookup.Count < CountOfEntries && !_lookup.ContainsKey(index))
{
if(_loader == null)
{
_loader = load().GetEnumerator();
}
while(_loader.MoveNext())
{
var pair = _loader.Current;
_lookup.Add(pair.Key,pair.Value);
if (pair.Key == index)
{
return index;
}
}
}
string name;
if (_lookup.TryGetValue(index,out name))
{
return return name;
}
throw new KeyNotFoundException("The given index was not found");
}
}
the code expectes the file to have one pair on each line like so:
index0,name0
index1,name1
If the first index sought is at the end this will perform slower probably (due to IO mainly) but if the access is random the average case woul be reading half of the values the first time if the access is not random make sure to keep the most used in the top of the file
there are a few more issues to considere. The above code is not threadsafe for the load operation and to increase responsiveness of the rest of the code keep the loading in a background thread
hope this helps
What about using a dictionary instead of two arrays? You could initialize the dictionary asynchronously using a thread or thread pool. The lookup would be O(1) instead of O(log(n)) as well.
public static class Lookup
{
private static readonly ManualResetEvent m_Initialized = new ManualResetEvent(false);
private static readonly Dictionary<int, string> m_Dictionary = new Dictionary<int, string>();
public static Lookup()
{
// Start an asynchronous operation to intialize the dictionary.
// You could use ThreadPool.QueueUserWorkItem instead of creating a new thread.
Thread thread = new Thread(() => { Initialize(); });
thread.Start();
}
public static string Lookup(int code)
{
m_Initialized.WaitOne();
lock (m_Dictionary)
{
return m_Dictionary[code];
}
}
private static void Initialize()
{
lock (m_Dictionary)
{
m_Dictionary.Add(0x0000, "Exclamation Point");
// Keep adding items to the dictionary here.
}
m_Initialized.Set();
}
}

Categories