Sunday, 30 August 2015

Thread Synchronization with Mutex and How to Implement it in C# & VB

Previously, I have posted about acquiring exclusive lock with SpinLock http://jaryl-lan.blogspot.com/2015/08/thread-synchronization-with-spinlock.html. Today, we will look into how to implement and use the Mutex. [I would like to give credits to Serena Yeoh for introduce this to me.]

The purpose for SpinLock and Mutex are quite similar, which is for applications that deal with multiple threads and every threads requires to have exclusive right to perform a task. But unlike SpinLock, Mutex are not limited to current process and can share across different processes. In Mutex, threads that are waiting for acquiring the lock are waiting for signal from the thread that is holding the lock.

To use the Mutex, An instance of a Mutex is required.

[C#]
Mutex mutex = new Mutex();

[VB]
Dim mutex As Mutex = New Mutex()

The code above can only be used in the current process. To share the Mutex across other processes, you need to give the Mutex a name. Here are a few things to take note when instantiating an instance of Named Mutex. For more details, https://msdn.microsoft.com/en-us/library/system.threading.mutex.aspx & https://msdn.microsoft.com/en-us/library/windows/desktop/ms682411(v=vs.85).aspx.
  • The name given to the Mutex are case sensitive, so make sure to take note of the name's casing when you want to share the same Named Mutex across your applications.
  • There are two types of prefix, which is "Global\" and "Local\". By default, if you do not specify any prefix for the Named Mutex, it will be "Local\".
  • If you need to share your Mutex across different Environment (For Example: Web Application, Windows Application), you need to include the prefix "Global\" in the name of the Mutex.
  • Other than prefix, the remaining character for the Named Mutex cannot contain backslash (\).
Other than that, you need to define the security access for the Mutex. This is to allow other processes that are launched by different user to share the same Mutex.

What the following code does is to try and get the existing Named Mutex. If is doesn't exist, a new Named Mutex will be created. Regarding the parameter MutexRights, specifying synchronize is to allow the thread to wait for the Named Mutex's lock. As for Modify, it is to allow the thread to release the lock of the Named Mutex.

The SecurityIdentifier is to define what kind of users can use the Named Mutex, in this case, specifying WorldSid is to allow all users (also known as Everyone) to use the Named Mutex.

[C#]
if (!Mutex.TryOpenExisting(MUTEX_NAME, MutexRights.Synchronize | MutexRights.Modify, out mutex))
{
    bool createdNew;
    MutexAccessRule mutexAccessRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.Synchronize | MutexRights.Modify, AccessControlType.Allow);

    MutexSecurity mutexSecurity = new MutexSecurity();
    mutexSecurity.AddAccessRule(mutexAccessRule);

    mutex = new Mutex(false, MUTEX_NAME, out createdNew, mutexSecurity);
}

[VB]
If mutex.TryOpenExisting(MUTEX_NAMEMutexRights.Synchronize Or MutexRights.Modify, mutex) Then
    Dim createdNew As Boolean
    Dim mutexAccessRule As MutexAccessRule = New MutexAccessRule(New SecurityIdentifier(WellKnownSidType.WorldSid, Nothing), MutexRights.Synchronize Or MutexRights.Modify, AccessControlType.Allow)

    Dim mutexSecurity As MutexSecurity = New MutexSecurity()
    mutexSecurity.AddAccessRule(mutexAccessRule)

    mutex = New Mutex(False, MUTEX_NAME, createdNew, mutexSecurity)
End If

mutex.WaitOne is to acquire the lock and wait for the lock to be released if is owned by other thread.

[C#]
mutex.WaitOne();

[VB]
_mutex.WaitOne()

mutex.ReleaseMutex is to release the lock and to enable other threads to acquire the lock.

[C#]
mutex.ReleaseMutex();

[VB]
_mutex.ReleaseMutex()

By using the same scenario as specified in my previous blog post about SpinLock. Race Condition will not happen if used together with Mutex. By running the sample code for SpinLock and Mutex, you will notice that SpinLock are much faster compared to Mutex.

The test is run with the following specification:
Operating System: Windows Server 2012 R2 64 Bit
Processor: Intel Core i7-4800MQ Processor
RAM: 16GB, Dual Channel, DDR3

Parallel Loop for 1,000,000 times.
Elapsed time for SpinLock: 126.08 ms ~ 129.57 ms
Elapsed time for Mutex: 2774.81 ms ~ 2868.85 ms

Hold it. Don't jump to a conclusion that SpinLock is better than Mutex. In this test, what i'm doing is just changing a single variable value. This means that each threads acquire the lock and release it in a very short duration, in which it can be ideal for SpinLock. But if the thread takes a very long time to complete a task, you will see the performance of the application starts to degrade. SpinLock will also affect other processes' performance while waiting for the lock to be release from the thread, since it uses CPU cycle while spinning in the loop.

You can get the sample code about Mutex from the following link. https://onedrive.live.com/redir?resid=E6612168B803803D!334&authkey=!ACaO5bWfJ1DdEJs&ithint=file%2czip




Wednesday, 26 August 2015

Programmatically Change Values in Configuration File During Runtime in C# & VB

In this post, I will show you guys on how to programmatically change the values defined in configuration file. [Thanks to Serena Yeoh for introduce this to me.]

"Be aware that it is not recommended to change the value in web application's configuration file, this is due to changing of the configuration file will cause the application pool to restart. What this means is that the value kept in session or in static will be lost."

Well, don't be scared off by the statement. It doesn't mean that you can't use it in different environment. There might be a situation that requires you to change the value in configuration file, such as the value defined in configuration file changes the way how your application behaves and you want to test these behaviors in your Unit Test. Changing the configuration value manually and re-run the test can be very tedious and other developers that are sharing/developing the same project might not be aware about this.

To deal with this kind of situation, you will need to change them in code. So let's get started.

You need to have an instance of Configuration. By calling the following code, it will retrieve the current project's configuration file (app.config).

[C#]
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

[VB]
Dim config As Configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)

If your application is using a custom configuration and wants to change the value in the custom configuration, you will need to get the instance of the section. Assuming my section's name is "sampleSectionGroup/changeConfiguration".

[C#]
var configSection = (ChangeConfigurationSection)config.GetSection("sampleSectionGroup/changeConfiguration");

[VB]
Dim configSection = CType(config.GetSection("sampleSectionGroup/changeConfiguration"), ChangeConfigurationSection)

With the configuration retrieved, you can then change the configuration value. The following code is used to change the value in appSettings. Assuming my appSettings contain keys with the name "sampleAppKeyOne" and "sampleAppKeyTwo".

[C#]
config.AppSettings.Settings["sampleAppKeyOne"].Value = "NewSampleAppKeyOne";
config.AppSettings.Settings["sampleAppKeyTwo"].Value = "NewSampleAppKeyTwo";

[VB]
config.AppSettings.Settings("sampleAppKeyOne").Value = "NewSampleAppKeyOne"
config.AppSettings.Settings("sampleAppKeyTwo").Value = "NewSampleAppKeyTwo"

The following code is used to change the value in a custom made configuration. Assuming my element name is "sampleConfig" that contain 2 string attribute "samplePropertyOne" and "samplePropertyTwo".

[C#]
configSection.SampleConfig.SamplePropertyOne = "NewSamplePropertyOne";
configSection.SampleConfig.SamplePropertyTwo = "NewSamplePropertyTwo";

[VB]
configSection.SampleConfig.SamplePropertyOne = "NewSamplePropertyOne"
configSection.SampleConfig.SamplePropertyTwo = "NewSamplePropertyTwo"

Once you have done changing the value. You need to save them back to the configuration file.

[C#]
config.Save(ConfigurationSaveMode.Modified);

[VB]
config.Save(ConfigurationSaveMode.Modified)

If you have the need to access the updated value from the configuration file immediately after the changes is saved to the configuration file. you need to refresh the section that you have changed. So if let's say the appSettings and the custom configuration's value is changed and need to get the updated value from the configuration file. those section needs to be refreshed by calling the following code.

[C#]
ConfigurationManager.RefreshSection("appSettings");
ConfigurationManager.RefreshSection("sampleSectionGroup/changeConfiguration");

[VB]
ConfigurationManager.RefreshSection("appSettings")
ConfigurationManager.RefreshSection("sampleSectionGroup/changeConfiguration")

The sample code can be obtained here https://onedrive.live.com/redir?resid=E6612168B803803D!331&authkey=!AGahxzzrDJsW3MM&ithint=file%2czip

Wednesday, 19 August 2015

Using MSMQ with WCF in C# & VB

You might come across a situation where data doesn't need to be process immediately or the data can be processed at a later time. There might be also a situation where you need to pass the data to another client that are currently offline or not available. In such a case, you opt for MSMQ to deal with these situations. Before continue reading, you need to have knowledge on what MSMQ is all about. So, if you are new to MSMQ, do take a look on the following link https://msdn.microsoft.com/en-us/library/ms711472(v=vs.85).aspx.

Now I'm going to show you how to implement MSMQ with WCF. This means that the application will send and receive message from the queue through service. Other than that, transactional queue will be used to perform retry on the queue message.

Firstly, implement a service and contract for receiving and processing the message in the queue. The parameter TransactionScopeRequired in the OperationBehavior needs to be set to true. This is to ensure that whenever there's an exception that prevents the method from complete, it will go back to the queue. For more detail about Transacted MSMQ binding, you can check it out from here https://msdn.microsoft.com/en-us/library/ms751493(v=vs.110).aspx.

[C#]
[ServiceContract]
public interface IRecoveryService
{
    [OperationContract(IsOneWay = true)]
    void Log(string value);
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)]
public class RecoveryService : IRecoveryService
{
    [OperationBehavior(TransactionScopeRequired = true)]
    public void Log(string value)
    {
        // Do your stuff
    }
}

[VB]
<ServiceContract>
Public Interface IRecoveryService
    <OperationContract(IsOneWay:=True)>
    Sub Log(ByVal value As String)
End Interface

<ServiceBehavior(InstanceContextMode:=InstanceContextMode.PerCall, ConcurrencyMode:=ConcurrencyMode.Single)>
Public Class RecoveryService
    Implements IRecoveryService

    <OperationBehavior(TransactionScopeRequired:=True)>
    Public Sub Log(value As String) Implements IRecoveryService.Log
        ' Do your stuff
    End Sub
End Class


The following are the sample configuration for hosting msmq with WCF. Assuming that my queue is a transactional private queue with the name wcfmsmq and my msmq service name is RecoveryService.

<system.serviceModel>
  <serviceHostingEnvironment multipleSiteBindingsEnabled="true">
    <serviceActivations>
      <add factory="System.ServiceModel.Activation.ServiceHostFactory" relativeAddress="./RecoveryService.svc" service="WCFMSMQVB.Services.RecoveryService" />
    </serviceActivations>
  </serviceHostingEnvironment>
  <services>
    <service name="WCFMSMQVB.Services.RecoveryService" behaviorConfiguration="DefaultServiceBehavior">
      <endpoint name="netMsmqRecoveryService" address="net.msmq://localhost/private/wcfmsmq" binding="netMsmqBinding" bindingConfiguration="netMsmq" contract="WCFMSMQVB.Services.Contracts.IRecoveryService" />
      <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <behavior name="DefaultServiceBehavior">
        <serviceMetadata httpGetEnabled="true" />
        <serviceDebug includeExceptionDetailInFaults="true" />
      </behavior>
    </serviceBehaviors>
  </behaviors>
  <bindings>
    <netMsmqBinding>
      <binding name="netMsmq" maxReceivedMessageSize="2147483647" maxRetryCycles="3" retryCycleDelay="00:00:05" receiveErrorHandling="Drop">
        <security mode="None">
          <transport msmqAuthenticationMode="None" msmqProtectionLevel="None" />
        </security>
      </binding>
    </netMsmqBinding>
  </bindings>
  <client>
    <endpoint address="net.msmq://localhost/private/wcfmsmq" binding="netMsmqBinding"
              bindingConfiguration="netMsmq" contract="RecoveryService.IRecoveryService"
              name="netMsmqRecoveryService" />
  </client>
</system.serviceModel>

If you tried to run your project with IIS Express and call the msmq service, you will hit with this error "The protocol 'net.msmq' is not supported.". This is because IIS Express does not support net.pipe protocol. You need to host them to your IIS. For more detail about IIS Express, you can check out from the following link http://www.iis.net/learn/extensions/introduction-to-iis-express/iis-express-faq.

When deploying your msmq service to IIS, make sure that your web site contain the net.msmq binding and the Enabled Protocols contains net.msmq. Otherwise you will get hit with the error message "The protocol 'net.msmq' is not supported."

To simplify the implementation to call msmq service, add a service reference (in this case is RecoveryService) to your project. Then call the service's method and the data will be sent to msmq. If you noticed that the data is in the queue and did not get process, this is due to your msmq service is not active. Just invoke the msmq service url and it will become active and process the queue message.

[C#]
var proxy = new RecoveryServiceClient();

try
{
    proxy.Log(value);
}
finally
{
    proxy.Close();
}

[VB]
Dim proxy As RecoveryServiceClient = New RecoveryServiceClient()

Try
    proxy.Log(value)
Catch ex As Exception
    proxy.Close()
End Try


For the binding value configured in netMsmqBinding section in the sample configuration defined above:
maxReceivedMessageSize - To specify how large the data is allowed to be sent through WCF service,
maxRetryCycles - Define the number of times to try before performing the action specified at receiveErrorHandling attribute,
retryCycleDelay - The amount of waiting time before performing the next retry,
receiveErrorHandling - The action to be done after reached the maximum number of retry as specified in maxRetryCycles attribute.
For more details on what other attributes can be configured to the netMsmqBinding section can be found here https://msdn.microsoft.com/en-us/library/ms731380(v=vs.110).aspx.

So, based on the values specified, if the method fail to process, it will place the data back to the queue and wait for 5 seconds before trying to process the data again. After retried for 3 times, which is the maximum number of retry as configured, MSMQ will remove the data from the queue. The reason why it is being removed from the queue is because Drop is specified in the receiveErrorHandling attribute.

If you do not want the message to be removed from the queue after reached the maximum number of retry attempt, you can consider moving the poison message to the sub-queue by assigning value Move to the receiveErrorHandling attribute.

For more details on handling poison message or to move them into poison message sub-queue and handle the message in the sub-queue, you can refer to https://msdn.microsoft.com/en-us/library/aa395218(v=vs.110).aspx.

Here's the sample code that are developed in layered by following http://serena-yeoh.blogspot.com/2014/03/layered-architecture-solution-guidance.html: C#: https://onedrive.live.com/redir?resid=E6612168B803803D!356&authkey=!AESnIsw8nRxITpY&ithint=file%2czip
VB: https://onedrive.live.com/redir?resid=E6612168B803803D!357&authkey=!AHKlSmIMOkYn-nQ&ithint=file%2czip

Read further if you want to run the sample project.

To run the sample, create a transactional msmq with the name wcfmsmq and publish the project that ends with Hosts.Web to your IIS, since IIS Express does not support net.msmq protocol.

To call the method to send data to MSMQ with WCF Service, you can either call it using the WCFTestClient application or run the project that ends with UI.Web and hit the button that displayed on the page. Do make sure to change the endpoint address in the configuration file located in the project that ends with UI.Web and point it to the project that you had published to IIS before hitting on the button.

Once you hit the button, it will assume that the method had failed and send the data to the queue. To simulate the retry mechanism until the MSMQ drop the data from the queue, the method that handles the MSMQ data will check for the text file existence and throw exception if is doesn't exist.

If you want the queue to process the data successfully, change the appSettings' logPath in the hosts.web to your desired location and create a folder name "SampleLog" with the extension ".txt". Or if you prefer to have your own implementation, just change the method "Log" implementation to your desired behavior in the RecoveryComponent file.

Friday, 14 August 2015

Creating zip file with ZipArchive in C# & VB

It is common for us to develop a function to compress physical files or any content generated from our code into zip archives. To implement the functionality, we may opt to use third party libraries to do so. If your project can target .NET Framework 4.5 and above, then you are able to use ZipArchive for file(s) or content compression.

Here are some stuff that ZipArchive can do:
1. Compress 1 or more files into a new or existing zip file.
2. The name of the file(s) can be changed before compress it to the zip file.
3. Compress content generated in codes, specify the file for the content to be stored into zip file.
4. Delete 1 or more files in the zip file.
5. Extract files.
6. 3 levels from compression (Fastest, Optimal, NoCompression).
7. Compress content or files into stream.

Without further ado, Let us check out how to use the ZipArchive. To use the ZipArchive, you need to have the following references. If you want to do more with ZipArchive, you need to have a reference to the System.IO.Compression.FileSystem namespace.

[C#]
using System.IO.Compression;

[VB]
Imports System.IO.Compression


Next is to initialize the ZipArchive.
  • archiveFileName: The location of the zip file.
  • mode: Action to be taken to the zip file. 
    • 3 Modes
      • Create : For creating a new zip file.
      • Read : For accessing the zip file content.
      • Update: For changing the zip file content.
[C#]
var zipArchive = ZipFile.Open(archiveFileName, mode);

[VB]
Dim zipArchive As ZipArchive = ZipFile.Open(archiveFileName, mode)


After initializing the ZipArchive, you can start compressing, deleting or extracting files. Let's start with extracting files. By executing the following code, all the files in the zip will be extracted and placed in a folder. The location of the folder is based on what you specified in the parameter.
  • destinationDirectoryName: Define the location for extracting the content in the zip file.
[C#]
zipArchive.ExtractToDirectory(destinationDirectoryName);

[VB]
zipArchive.ExtractToDirectory(destinationDirectoryName)


For the following code, it is used to compress physical file into the zip file.
  • sourceFileName: The physical file location. 
  • entryName: The name of the physical file when compress it to zip file. 
  • compressionLevel: Define the CompressionLevel of the file. 
    • 3 CompressionLevel 
      • Fastest: Compress the file quickly.
      • Optimal: Compress the file optimally.
      • NoCompression: No compression done on the file.
[C#]
zipArchive.CreateEntryFromFile(sourceFileName, entryName, compressionLevel);

[VB]
zipArchive.CreateEntryFromFile(sourceFileName, entryName, compressionLevel)


And finally, the following code is to remove the file located inside the zip file.
  • entryName: The name of the file located in the zip file.
[C#]
var zipArchiveEntry = zipArchive.GetEntry(entryName);
zipArchiveEntry.Delete();

[VB]
Dim zipArchiveEntry As ZipArchiveEntry = zipArchive.GetEntry(entryName)
zipArchiveEntry.Delete()

If you want to compress files or content into a stream or stream the compressed content through WCF, you can do so with ZipArchive. Other than that, please remember to dispose of any disposable objects after you have finished using them, this is to prevent any memory leak from happening. You can dispose them by calling the .Dispose() method or use the using statement.

For more details on how to use ZipArchive and how to use stream with ZipArchive, you can check out the sample project here. https://1drv.ms/u/s!Aj2AA7hoIWHmgnaTDEvJCLxcXVtt