Since MultiCharts .NET makes use of C#, there are several ways to implement a global storage solution within C# itself without resorting to GlobalVariabe.dll . A native C# solution has the advantage of being convenient for the user to modify as desired. After some thought, I decided to implement an approach using the ConcurrentDictionary class, one of several thread-safe collections added by the System.Collections.Concurrent namespace introduced in .NET Framework 4. This has worked out well for me thus far, so I thought I'd share the technique and my Globals class for the MC .NET community to use.
A ConcurrentDictionary works by specifying key/value pairs just like the regular generic Dictionary type available prior to .NET 4. We can create a static Globals class to store such dictionaries for access from any indicator or strategy in MultiCharts .NET. As an example, to create a ConcurrentDictionary called NamedInteger for storing integers that will be accessed by a string name, we could do it in the following way inside the Globals class:
Code: Select all
static ConcurrentDictionary<string, int> NamedInteger = new ConcurrentDictionary<string, int>();
Code: Select all
Globals.NamedInteger["Length"] = 4;
Code: Select all
int myLength = Globals.NamedInteger["Length"];
Code: Select all
static ConcurrentDictionary<int, int> NumberedInteger = new ConcurrentDictionary<int, int>();
Code: Select all
int myLength = 10; // Default value
int retrievedValue = 0;
if (Globals.NamedInteger.TryGetValue("Length", out retrievedValue))
{
myLength = retrievedValue;
}
The C# Globals class I've created stores a set of dictionaries that provide global storage for the same data types supported by TS's GlobalVariable.dll (int, float, double, bool, and string). These dictionaries are completely independent of any MC .NET types, but I've placed the class in the PowerLanguage namespace for easy access without requiring a "using" clause. The dictionaries were created in a manner similar to the examples shown above, but using properties for accessing the dictionaries. Since each property simply returns a ConcurrentDictionary, the syntax for using a property for access is identical to the examples shown above for directly accessing a dictionary itself. There are five dictionaries accessed by string name, and five that are accessed by a numeric index:
NamedInteger
NamedFloat
NamedDouble
NamedBool
NamedString
NumberedInteger
NumberedFloat
NumberedDouble
NumberedBool
NumberedString
The attached "globals.zip" file contains the Globals class in a couple of alternative forms that you can use to install it for MC .NET use. Unzip the file to any convenient temporary folder, then choose one (not both at the same time!) of the following approaches:
1. Within the MC .NET editor, import the "Globals.pln" file. The Globals class will then be imported as a MC .NET "function", although it is not a function. We're just using this as a means to sneak some code into MC .NET for compilation, as described in the "MultiCharts .NET Programming Guide" on page 86 (see steps under item #2 on that page). As noted in the Guide, such "functions" will always be colored in red in the MC .NET editor, indicating not compiled. This is OK according to the Guide, since we're just using the file for code storage. I recommend using "Recompile All" (CTL-F7) any time you modify the Globals class or any indicators and signals using the class. Having the actual code for the Globals class, as we accomplish with this approach, is useful so that you can see how it is implemented and also to experiment with changes to it if desired. However, as noted on page 87 of the Guide, using a MC .NET function file for storing general code can have some undesired compilation side effects in some situations. If those side effects turn out to be a problem for you, then use approach #2.
2. Instead of approach #1, you can simply use the Globals.dll assembly provided in the zip file (or just create it yourself using Visual Studio). Just place the assembly in any folder you like (the MC .NET installation folder is convenient), and add a reference to it from the MC .NET editor before you use it. It works with both 32-bit and 64-bit MultiCharts and Windows.
Be aware that using any kind of global storage solution in a multi-threaded environment requires careful thought. Although the ConcurrentDictionary type is specifically designed to be thread-safe and optimized for multi-threaded use, being thread-safe only means that the collection itself is safe for multi-threaded access. If you are allowing code from multiple threads to read and write to the exact same dictionary keys within a dictionary, you may also need to work out your own thread synchronization code and special locks. However, for the most common usage cases for global storage in MC .NET, you should be able to use the dictionaries provided by the Globals class and use the built-in ConcurrentDictionary methods without needing to add any complex synchronization code.
I've found the Globals class to be a good global storage solution for my purposes in MultiCharts .NET, and I've successfully used it in a recent project when re-engineering EasyLanguage code to C#, where the EasyLanguage code had used TS's GlobalVariable.dll for global storage.
In a separate post to this thread, I'll provide an example of how to use the Globals class to accomplish sharing of settings between a strategy and an indicator.