|
I've run into a situation I haven't seen before, and was wondering if someone with a bit more threading experience would like to chime in.
The class IsoCurrencyInfo maintains a collection of IsoCurrencyInfo singletons. The instances of IsoCurrencyInfo class themselves are read-only once created, so by themselves are thread-safe. The trick is keeping the ArrayList container in line. I think I have it nailed, but in doing so I am executing a return statement while inside a lock() .
The code works very well under heavy concurrent load , but I can't help wondering "Is this safe?" Is there a better way to structure this method to optimize the locking?
I have adapted the Singleton implementation pattern[^] from Microsoft Patterns & Practices[^].
public static IsoCurrencyInfo GetInstance(string isoCode)
{
IsoCurrencyInfo newICI = null;
if(null == _iciRegistry)
lock(syncRoot)
if(null == _iciRegistry)
{
_iciRegistry = new ArrayList();
newICI = new IsoCurrencyInfo(isoCode);
_iciRegistry.Add(newICI);
}
if(null == newICI)
lock(syncRoot)
{
foreach(IsoCurrencyInfo existingICI in _iciRegistry)
if(existingICI.AlphaCode == isoCode)
return existingICI;
newICI = new IsoCurrencyInfo(isoCode);
_iciRegistry.Add(newICI);
}
return newICI;
}
Thanks!
B
|
|
|
|
|
It's completely safe. The lock keyword translates to the following (verifiable if you use ildasm.exe or some other disassembler / decompiler to view the compiled code):
Monitor.Enter(syncRoot);
try
{
}
finally
{
Monitor.Exit(syncRoot);
} The finally block is always run - regardless of a return or a throw - except when Environment.Exit is called (which unloads the process and the CLR completely, thus it really won't matter that the lock wasn't released because the OS will reclaim any process resources).
-----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-----
|
|
|
|
|
Thank you for a solid example. I didn't think of checking my decompiler's output.
|
|
|
|
|
Brandon,
Returning inside a lock is okay.
I don't necessarily see anything incorrect about your implementation. However, the double-checked locking pattern is essentially useless as you have used it since you'll always be aquiring at least one lock anyway. I would suggest the following code...
public class IsoCurrencyInfo
{
private static Hashtable _iciRegistry = new Hashtable();
public static IsoCurrencyInfo GetInstance(string isoCode)
{
if (!_iciRegistry.Contains(isoCode))
{
lock (syncRoot)
{
if (!_iciRegistry.Contains(isoCode))
{
_iciRegistry.Add(isoCode, new IsoCurrencyInfo(isoCode));
}
}
}
return (IsoCurrencyInfo)_iciRegistry[isoCode];
}
}
It is important to realize that the Hashtable is the only IDictionary collection that will work as I have used it. This is because the Hashtable can support multiple readers and one writer simultaneously. Likewise, you won't be able to use the same trick with an ArrayList. In this implementation the lock is rarely acquired.
Brian
|
|
|
|
|
Bravo!
Based on your code and some thought, I ended up restructuring the entire class. It is smaller, tighter, and a lot faster. My test suite execution time dropped from an average of more than 500ms to less than 200ms; it drops to less than 1ms when I pre-load the singletons. That lock-loop was killing me.
Thanks!
B
|
|
|
|
|
hai everybody... may i know how to write the coding for the log off, reboot and shut down function in C# language. The coding must be able to use own pc so such to control others pc... I got a sample code which is written in VB6 as below:
Private Sub butLogOff_Click()
SystemFunc "logoff"
End Sub
Private Sub butReboot_Click()
SystemFunc "reboot"
End Sub
Private Sub butShutdown_Click()
SystemFunc "shutdown"
End Sub
Private Sub SystemFunc(task As String)
Const CONST_SHUTDOWN = 1
Const CONST_LOGOFF = 0
Const CONST_POWEROFF = 8
Const CONST_REBOOT = 2
Const CONST_FORCE_REBOOT = 6
Const CONST_FORCE_POWEROFF = 12
Const CONST_FORCE_LOGOFF = 4
Const CONST_FORCE_SHUTDOWN = 5
Dim objInstance, objEnumerator, cmdValue, intStatus
Select Case task
Case "logoff"
cmdValue = CONST_LOGOFF
Case "reboot"
cmdValue = CONST_REBOOT
Case "shutdown"
cmdValue = CONST_SHUTDOWN
End Select
Set objEnumerator = objService.ExecQuery("Select * From Win32_OperatingSystem", , 0)
For Each objInstance In objEnumerator
intStatus = objInstance.Win32ShutDown(cmdValue)
If intStatus = 0 Then
ShowStatus "System Function call successful."
Else
ShowStatus "System Function call failed!"
End If
Next
End Sub
|
|
|
|
|
The WMI support in .NET is superb. The best way to do this is to create a new project, then open your Server explorer (the "Server" tab next to the "Toolbox" in the default VS.NET installation) add your computer unders Servers (if it isn't already), then drill-down the find the Management Classes node. If you don't see them, download the setup at http://go.microsoft.com/fwlink/?LinkId=3353[^].
Now find the Operating Systems node. Right-click and click Generate Managed Class. Now you have the Win32_OperatingSystem class encapsulated in a .NET class you can use in many ways! This will have several methods for what you need, such as a Shutdown and Reboot method.
You can then, for example, reboot a named machine like so:
ManagementScope scope = new ManagementScope(
string.Format(@"\\{0}\ROOT\CIMV2", name));
Sample.ROOT.CIMV2.OperatingSystem.OperatingSystemCollection systems =
Sample.ROOT.CIMV2.OperatingSystem.GetInstances(scope, null, null);
foreach (Sample.ROOT.CIMV2.OperatingSystem system in systems)
system.Reboot(); Sample is the just the namespace I used to write the example code. The Sample.ROOT.CIMV2 namespaces and the classes and nested classes therein where generated from the step above.
-----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-----
|
|
|
|
|
Could somebody give me a smidge of help with the System.Windows.Forms.MonthCalendar class? Or at least point me to some good tutorials using it.
All I'm trying to do at this point is this:
After a user has selected some dates in it, I'd like to go through the entire range of dates (or at least a reasonable portion) and get all selected dates that the user selected. I want to store those dates into an array of DateTime objects.
Any help or pointers? Thanks.
There are only 10 types of people in this world....those that understand binary, and those that do not.
|
|
|
|
|
You can use the SelectionRange (or the SelectionStart and SelectionEnd properties) to iterate between the start and end dates. You cold either temporarily add these to a growable ArrayList , or calculate the number of elements a DateTime[] array would require. The following uses the latter method:
TimeSpan span = monthCal.SelectionEnd - monthCal.SelectionStart;
int count = span.Days + 1;
DateTime[] dts = new DateTime[count];
for (int i=0; i<count; i++)
dts[i] = monthCal.SelectionStart + new TimeSpan(1, 0, 0, 0);
-----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-----
|
|
|
|
|
Thanks for the reply. That looks fairly straightforward. I'm not familiar with the TimeSpan class (yet), but it looks relatively straightwforward.
But this allows me to traverse it....is there anything in that TimeSpan class that lets me see whether the date in question is selected (highlighted in the control) or not?
There are only 10 types of people in this world....those that understand binary, and those that do not.
|
|
|
|
|
The TimeSpan structure - not class (read the SDK documentation for more details) - just represents a difference in relation to a DateTime . The MonthCalendar class only exposes a SelectionStart and SelectionEnd date (the SelectionRange only contains these two properties as well). The TimeSpan has nothing to do with this. See the MonthCalendar documentation in the .NET Framework SDK for more details.
-----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-----
|
|
|
|
|
Yes, I see how I could use that to select a certain day, but how from there can I tell if that day has been selected/highlighted by the user? I've gone through documentation and this is my primary problem.
Thanks though.
There are only 10 types of people in this world....those that understand binary, and those that do not.
|
|
|
|
|
As I keep saying, you must iterate through the dates between the MonthCalendar.SelectionStart and MonthCalendar.SelectionEnd dates. That snippet of code I posted the first time does this. The TimeSpan merely adds i days to the SelectionState DateTime and adds that to the array. The SelectionRange is contiquous to simply iterating inclusively between the SelectionStart and SelectionEnd dates is how you get an array of the selected dates.
-----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-----
|
|
|
|
|
How exactly, then, is it determining if the date was selected/highlighted? That snipped just appears to go through all the dates. Does the SelectionRange only give dates that were selected?
BTW....I'm at work now and unable to play with the code in question ("my own" code at home)....so I'm going by memory (e.g. code is not in front of me). That's why I'm unable to put this in and test and see what you mean.
There are only 10 types of people in this world....those that understand binary, and those that do not.
|
|
|
|
|
As I've mentioned a couple times now, the SelectionRange is inclusive, meaning that every date between MonthCalendar.SelectionStart and MonthCalendar.SelectionEnd is selected. Unless there's some undocumented feature of the MonthCalendar or you've extended and overridden its behavior, this is how the MonthCalendar works - a single date range can be selected.
Now, if you want to track every selection the user makes, handle the MonthCalendar.DateSelected event and add the range from DateRangeEventArgs.Start and DateRangeEventArgs.End to an ArrayList or something, which you can later use ArrayList.CopyTo to create an array from the list.
-----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've got it now and am only posting it here now for posterity. I must have been pretty tired when I worked on it last because it was right there as obvious as could be. I swear I went through the docs on the MonthCalendar class about 5 times and didn't see what I wanted, but NOW I see there is a property BoldedDates which returns to me an array of DateTime[] of all the dates that are bolded. Which is EXACTLY what I was trying to get.
Why it was so hard, I don't know. Like I said...I must have been tired...it was late last Saturday or Sunday night when I played with it last.
There are only 10 types of people in this world....those that understand binary, and those that do not.
|
|
|
|
|
You never said bolded dates - those are different from selected dates, hence even the different property names. If you had specified that before, I could've told you immediately; of course, if you had looked at the class members like I mentioned you should do before - i.e., read the documentation - it should'be been obvious.
There is a big difference between bolded and selected dates, though.
-----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-----
|
|
|
|
|
Hi all,
I would like to be able to determine at the start of my app if the user has enough permissions for many different files/folders.
I have read articles that discuss calling Win32 API NTFS calls, and Active Directory calls to get ACLs, but this seems like something that I would think would be inside dot net some how. No?
Like something like:
if( File.GetPermissions( "C:\\my cars" ) == FileAccess.Read | FileAccess.Write )
{
// good
}
else
{
MessageBox.Show( "Not enough permissions. );
}
Anyone got any ideas?
Thanks alot for any help you can lend,
Kris.
|
|
|
|
|
Krisp,
I do not know if this going to help you or not. But System.IO.File.GetAttributes(FileName)returns a file's attributes. Typical Attributes are Archive, ReadOnly and hidden, I am sure there is more.
Hope this helps!
|
|
|
|
|
No, that doesn't get any file permissions such as: can the user read/write.
I had looked at that myself as well.
But thanks anyways.
|
|
|
|
|
Thats ok, I was reading this on an other site. It deals with permissions.
http://www.codeguru.com/cs_misc/Security.html
|
|
|
|
|
No, there is currently nothing in the .NET base class library that deals with NTFS permissions. There may be some third-party libraries out there and I'm sure "Longhorn" will introduce such encapsulation, but you either have to use the NTFS APIs or try to write a zero-byte file to the directory and catch any exceptions that are thrown.
For more discussion about alternatives, please click the "Search Comments" link above. We have covered this in the past. There are also a few articles here on the CP web site. Use the search text box toward the top of the page (below the logo).
-----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-----
|
|
|
|
|
|
By P/Invoking the functions you need. See DllImportAttribute for more information. It would also be best to encapsulate this into a nice class or classes. It will give you and your clients a better object-oriented approach to dealing with CAB files.
-----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-----
|
|
|
|
|
what is the corrsponed type in C# that means the type void* in C++
|
|
|
|