@manhng

Welcome to my blog!

Performance Tips

August 24, 2021 10:51

Performance Tips (edit)

C#.NET Tutorials For Beginners and Professionals - Dot Net Tutorials

  • Enums
  • Strings
  • Arrays
  • Lists
  • Interfaces
  • Switch Statements
  • Operators

5) Contains method in HashSet<T> and List<T>

HashSet<T> Class (System.Collections.Generic) | Microsoft Docs

List<T> Class (System.Collections.Generic) | Microsoft Docs

Sourcec# - Performance Benchmarking of Contains, Exists and Any - Stack Overflow

  • HashSet<T>.Contains :     0 ms (10000 items)
  • List<T>.Contains        : 569 ms (10000 items)

image

Source: theburningmonk/HashSet-vs-List-vs-Dictionary: Simple performance test of HashSet<T> vs List<T> and Dictionary<TKey, TValue> (github.com)

How to use HashSet in C# | InfoWorld

HashSet vs List vs Dictionary | theburningmonk.com

So sánh tốc độ List collection và HashSet collection trong C# - Tungnt.net

4) String

  • Sử dụng StringBuilder với những đoạn code cộng chuỗi cho n (n > 3) phép cộng chuỗi sẽ tốt hơn dùng toán tử cộng chuỗi.
  • Sử dụng toán tử "+" chuỗi khi có tổng cộng n (n <= 3) phép cộng chuỗi.
  • Thử với String.Concat
  • Thử với String.Join(";", array);
  • Thử với String.Format
  • Thử với String interpolation: @$"{}"

3/ Integer

  • Sử dụng Int32.TryParse sẽ tốt hơn Int32.Parse

Not Good

numVal = Int32.Parse("-105")

Good

if (Int32.TryParse("-105", out int j)) // Does not throw exception

2/ Dictionary

Nếu bạn đang cố gắng lấy ra giá trị từ từ điển, thì TryGetValue (khóa, giá trị ngoài) là lựa chọn tốt nhất, nhưng nếu bạn đang kiểm tra sự hiện diện của khóa, để chèn mới, không ghi đè các khóa cũ, ContainsKey (khóa) là tùy chọn tốt nhất.

  • Sử dụng Dictionary.TryGetValue() sẽ tốt hơn Dictionary.ContainsKey() trong trường hợp cố gắng lấy ra giá trị từ từ điển.
  • Sử dụng Dictionary.ContainsKey() sẽ tốt hơn Dictionary.TryGetValue() trong trường hợp kiểm tra trùng lặp khóa để thêm phần tử vào Dictionary.

Usage:

if (counts.ContainsKey("key"))
if (counts.TryGetValue("key", out T value)) // Does not throw exception

1/ DataReader

  • Sử dụng DataReader.GetSchemaTable khi cần lấy tên cột và kiểu dữ liệu trả về.
    • DataTable schemaTable = reader.GetSchemaTable();
    • var colNames = schemaTable.Rows.Cast<DataRow>().Select(row => row["ColumnName"] as string).ToArray();
    • var colDataTypes = schemaTable.Rows.Cast<DataRow>().Select(row => (row["DataType"] as Type).Name).ToArray();
  • Sử dụng DataReader.InitialLOBFetchSize = -1 (đối với query có chứa trường LOB) sẽ tốt hơn với các trường LOB và dữ liệu trả về cho mỗi LOB gần giống nhau.
  • Sử dụng DataColumn.Ordinal (column ordinal) nhanh hơn dùng DataColumn.ColumnName (column name): faster using column ordinals instead of column names.

Đọc trường LOBs (BLOBs, CLOBs, and NCLOBs)

using (var conn = new OracleConnection(OracleConnString))
{
conn.Open();

using (var cmd = new OracleCommand(sql, conn))
{
var param = cmd.CreateParameter();
param.ParameterName = ":p__linq__0";
param.Value = 4879975843;
param.DbType = DbType.Int64;
cmd.Parameters.Add(param);

cmd.InitialLOBFetchSize = -1;
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
if (colNames.Contains("ORDER_CODE") && !reader.IsDBNull("ORDER_CODE"))
{
dto.ORDER_CODE = reader.GetValueOrDefault<String>("ORDER_CODE");
}
...

Kiểm tra ExistColumn

DataTable schemaTable = reader.GetSchemaTable();
string[] colNames = schemaTable.Rows.Cast<DataRow>().Select(row => row["ColumnName"] as string).ToArray();
string[] colDataTypes = schemaTable.Rows.Cast<DataRow>().Select(row => (row["DataType"] as Type).Name).ToArray();
if (colNames.Contains("ORDER_CODE") && !reader.IsDBNull("ORDER_CODE"))
{
dto.ORDER_CODE = reader.GetValueOrDefault<String>("ORDER_CODE");
}

Lấy giá trị khi đọc DataReader

public static class DataReaderExtension
{
public static bool IsDBNull(this IDataReader dataReader, string columnName)
{
return dataReader[columnName] == DBNull.Value;
}

public static T GetValueOrDefault<T>(this IDataRecord row, string fieldName)
{
int ordinal = row.GetOrdinal(fieldName);
return row.GetValueOrDefault<T>(ordinal);
}

public static T GetValueOrDefault<T>(this IDataRecord row, int ordinal)
{
return (T)(row.IsDBNull(ordinal) ? default(T) : row.GetValue(ordinal));
}
}

References

Const vs Static vs Readonly in C# (exceptionnotfound.net)

Retrieving Data Using a DataReader - Samir Daoudi's Technical Blog (daoudisamir.com)

Create a Windows Service in C# or Convert your Console App to a Service - Samir Daoudi's Technical Blog (daoudisamir.com)

Run part of your C# Code under a different user - Samir Daoudi's Technical Blog (daoudisamir.com)

C#, Authenticate against AD - Samir Daoudi's Technical Blog (daoudisamir.com)

Modal PoP Up in SharePoint using BootStrap - Samir Daoudi's Technical Blog (daoudisamir.com)

Run a C# .NET console application as a windows service

June 1, 2021 22:44

Run a C# .NET console application as a windows service (edit)

Run a C# .NET console application as a windows service

zaagan/HybridSvx: A Hybrid of a Windows Console App And a Windows Service (github.com)

manhng83/HybridSvx: A Hybrid of a Windows Console App And a Windows Service (github.com)

.NET Core

https://blog.computedcloud.com/background-services-in-net-core-console-app/

https://docs.hangfire.io/en/latest/deployment-to-production/making-aspnet-app-always-running.html

Task Scheduler in Windows

Chú ý: Phải add Users cho full quyền truy cập vào thư mục %LocalAppData%\HybridSvx\

How To Create a Scheduled Task in Windows 10 (c-sharpcorner.com)

Windows Admin: Using Task Scheduler to Run Processes Later (howtogeek.com)

Setup A Task Scheduler To Run Application Periodically In C# (c-sharpcorner.com)

Run a C# .NET console application as a windows service

Run a C# .NET console application as a windows service

Deploy to %LocalAppData%\HybridSvx\

This article will guide you through the necessary steps on creating a flexible hybrid application that is a mixture of a console application and a windows service. Takeaways : ⇒ Learn to create a runnable application which can later on be installed as a windows service. ⇒ A working template for your future usages available on Github.

Table Of Contents

Background

Most of the time, when I am assigned a new task like integrating a 3rd party tool or a plugin into my .NET based application, I simply rely on trying it out first hand via a simple Console application and quickly integrating the necessary parts. And that is what probably any .NET developer would do (some might have a different approach).

But, sometimes there are requirements where the task is to create a job or a service with a repetitive flow and made runnable in a scheduled fashion. Some common scenarios are creating a job for delivering messages and updates,  performing backups, doing cleanups and many more of such stuffs.

There are many options to achieve these requirements by using a third party tool. Some of those tools are: Hangfire, Quartz, Topshelf etc.

But, since I would have already tried out and tested the feature via a console application, my next step would be simply to deploy the code as a service. This generally involves, creating a new windows service application and integrating my previously tested code.

But instead of creating a new application, I do some tweaks here and there, improvise the old console application and make it behave as a windows service and vice-versa.  I can then easily install this console app as a windows service into my system whenever I want.

Lets see how it is done …

The Console Application

Basically we start by creating a new console application. Here is a simple console application that simply just writes to a file.

Program.cs file
class Program
{
    static void Main(string[] args)
    {
        DataProcessor dataProcessor = new DataProcessor();
        dataProcessor.Execute();
    }
}
DataProcessor.cs file
using System;
using System.IO;
using System.Reflection;

namespace HybridSvx
{
    internal class DataProcessor
    {

        internal void Execute()
        {
            try
            {
                LogMessage();
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception: " + e.Message);
            }
        }


        /// <summary>
        /// Writes a simple message to a file in the application directory
        /// </summary>
        private void LogMessage()
        {
            string assemblyName = Assembly.GetCallingAssembly().GetName().Name;
            string fileName = string.Format(assemblyName + "-{0:yyyy-MM-dd}.log", DateTime.Now);
            string filePath = AppDomain.CurrentDomain.BaseDirectory + fileName;

            string message = "Execution completed at " + DateTime.Now.ToShortTimeString();

            Console.WriteLine(message);
            using (StreamWriter sw = new StreamWriter(filePath, true))
            {
                sw.WriteLine(message);
                sw.Close();
            }
        }

    }
}

Setting Up The Windows Service

The next step would be to include the necessary libraries and write some code that are required in order to create a windows service. The steps are as follows:

Step 1: Add New Item

In your Visual Studio Console Project ⇒ Right click the project ⇒ Add ⇒ New Item

Add-New-Windows-Service-1
Step 2 : Add a new Windows Service

Search and select Windows Service ⇒ Provide a name eg: ‘HybridSvxService.cs‘ ⇒ Click Add

New-Windows-Service

This will add a new file which will contain your code that needs to be executed by the windows service.

The Windows service needs to be running continuously, else it will automatically stop after it has completed its execution. Hence, in order to make the service run continuously, we will introduce a simple timer as follows :

using System.ServiceProcess;
using System.Timers;

namespace HybridSvx
{
    partial class HybridSvxService : ServiceBase
    {
        private static Timer aTimer;

        public HybridSvxService()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            aTimer = new Timer(10000); // 10 Seconds
            aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
            aTimer.Enabled = true;
        }

        private static void OnTimedEvent(object source, ElapsedEventArgs e)
        {
            DataProcessor dataProcessor = new DataProcessor();
            dataProcessor.Execute();
        }

        protected override void OnStop()
        {
            aTimer.Stop();
        }

    }
}
Step 3 : Setup the Installer Class

You first need to add a reference to the System.Configuration.Install assembly via Project ⇒ Add ⇒ Reference.

Next, Add a new Class with a meaningful name eg ‘HybridSvxServiceInstaller.cs‘ and paste in the following code :

using System.ComponentModel;
using System.Configuration.Install;
using System.ServiceProcess;

namespace HybridSvx
{
    [RunInstaller(true)]
    public class HybridSvxServiceInstaller : Installer
    {
        public HybridSvxServiceInstaller()
        {
            ServiceProcessInstaller serviceProcessInstaller = new ServiceProcessInstaller();
            ServiceInstaller serviceInstaller = new ServiceInstaller();

            // Setup the Service Account type per your requirement
            serviceProcessInstaller.Account = ServiceAccount.LocalSystem;
            serviceProcessInstaller.Username = null;
            serviceProcessInstaller.Password = null;

            serviceInstaller.ServiceName = "HybridSvx";
            serviceInstaller.DisplayName = "HybridSvx Service";
            serviceInstaller.StartType = ServiceStartMode.Automatic;
            serviceInstaller.Description = "My custom hybrid service";

            this.Installers.Add(serviceProcessInstaller);
            this.Installers.Add(serviceInstaller);
        }

    }
}

The above code will provide your windows service with the necessary foundation for custom installation like the Service name and description, service account type etc.

Configure Self Installer

Adding a Self installer within the windows service itself, removes the hurdle of depending on a tool like InstallUtil.exe for installation. This makes the installation much easier and straight forward.

In your project, create a new class file with the name SelfInstaller.cs and paste the following code:

using System.Configuration.Install;
using System.Reflection;

namespace HybridSvx
{
    public class SelfInstaller
    {
        private static readonly string _exePath = Assembly.GetExecutingAssembly().Location;
        public static bool InstallMe()
        {
            bool result;
            try
            {
                ManagedInstallerClass.InstallHelper(new string[] {
                    SelfInstaller._exePath
                });
            }
            catch
            {
                result = false;
                return result;
            }
            result = true;
            return result;
        }

        public static bool UninstallMe()
        {
            bool result;
            try
            {
                ManagedInstallerClass.InstallHelper(new string[] {
                    "/u", SelfInstaller._exePath
                });
            }
            catch
            {
                result = false;
                return result;
            }
            result = true;
            return result;
        }

    }
}

Customize Program.cs

The final tweak would be to customize the Program.cs to support the functioning of both a console application and the windows service.

Summary : If you install the application, it will work as a windows service and if you directly run it, it will behave as a console application.

Code :

using System;
using System.ServiceProcess;

namespace HybridSvx
{
    class Program
    {
        static void Main(string[] args)
        {
            if ((!Environment.UserInteractive))
            {
                Program.RunAsAService();
            }
            else
            {
                if (args != null && args.Length > 0)
                {
                    if (args[0].Equals("-i", StringComparison.OrdinalIgnoreCase))
                    {
                        SelfInstaller.InstallMe();
                    }
                    else
                    {
                        if (args[0].Equals("-u", StringComparison.OrdinalIgnoreCase))
                        {
                            SelfInstaller.UninstallMe();
                        }
                        else
                        {
                            Console.WriteLine("Invalid argument!");
                        }
                    }
                }
                else
                {
                    Program.RunAsAConsole();
                }
            }
        }

        static void RunAsAConsole()
        {
            DataProcessor dataProcessor = new DataProcessor();
            dataProcessor.Execute();
        }

        static void RunAsAService()
        {
            ServiceBase[] servicesToRun = new ServiceBase[]
           {
                new HybridSvxService()
           };
            ServiceBase.Run(servicesToRun);
        }


    }
}

Running the Program

Now, you have a working application that can either run as a console application or be installed as a windows service. Here is how you can run the application in both ways :

As a Console Application

Simply double click to run the application

As a Windows Service
  1. Navigate to the project output directory and locate HybridSvx.exe.
  2. Fire up a command prompt with an administrator privilege.
  3. To Install ⇒ type HybridSvx.exe -i
  4. To Uninstall ⇒ type HybridSvx.exe -u
  5. To View the service ⇒ Press Win + R ⇒ type services.msc
Services-msc

Windows Service

June 29, 2020 17:33

Windows Service (edit)

  • Windows.Forms applications
  • Using a System.Windows.Forms.Timer (not System.Threading.Timer) to peform GUI updates is also a good solution.
  • Let xxx run in background

Idea

https://stackoverflow.com/questions/11027051/develop-a-program-that-runs-in-the-background-in-net

Source Code

https://github.com/UweKeim/SimpleBackup

https://github.com/MscrmTools/MscrmTools.Iconator (Manage custom entities icons in a single screen)

https://github.com/IBM/HTTP-BlackOps

https://github.com/IBM/HTTP-BlackOps/tree/master/CustomTestsUI

https://github.com/sunpander/YYERP

https://github.com/Autodesk/synthesis

https://github.com/Gangleider/WorkSoap

Windows Service

https://www.howtogeek.com/school/using-windows-admin-tools-like-a-pro/lesson8/

https://www.howtogeek.com/50364/convert-a-batch-bat-script-to-an-executable-exe-file/

https://stackoverflow.com/questions/3243348/how-to-call-a-method-daily-at-specific-time-in-c (HAY HAY HAY)

https://stackoverflow.com/questions/246697/best-timer-for-using-in-a-windows-service (HAY HAY HAY)

Both System.Timers.Timer and System.Threading.Timer will work for services

Task Scheduler

https://www.calazan.com/windows-tip-run-applications-in-the-background-using-task-scheduler/

https://www.codeproject.com/Articles/2407/A-New-Task-Scheduler-Class-Library-for-NET

Background Jobs

https://docs.microsoft.com/en-us/azure/architecture/best-practices/background-jobs

Set CPU Process Priority Applications in Windows 10

https://www.tenforums.com/tutorials/89548-set-cpu-process-priority-applications-windows-10-a.html

How to launch apps automatically during startup on Windows 10

https://www.windowscentral.com/how-launch-apps-automatically-during-startup-windows-10

Background Worker

https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.backgroundworker?view=netframework-4.5

https://devtut.github.io/csharp/backgroundworker.html

https://carldesouza.com/c-using-backgroundworker/

https://viblo.asia/p/backgroundworker-trong-ung-dung-c-windows-form-naQZRGy0lvx

Backgrounder

https://code.google.com/archive/p/backgrounder/

.NET Framework 4.0

https://www.codeproject.com/Articles/106742/Creating-a-simple-Windows-Service

.NET Core 3.0

https://codeburst.io/create-a-windows-service-app-in-net-core-3-0-5ecb29fb5ad0

How to run background task in Outlook 2007 add-in efficiently?

  • OOM: Office Object Mode
  • OOM: Outlook Object Mode
  • COM: Component Object Model (COM)
  • VSTO Outlook Multi threading
  • VSTO Outlook Addin
  • VSTO Addin for Outlook
  • MAPI: Messaging Application Programming Interface
  • EWS: Exchange Web Services

https://stackoverflow.com/questions/2456483/how-to-run-background-task-in-outlook-2007-add-in-efficiently

https://stackoverflow.com/questions/47312985/vsto-outlook-multithreading

https://stackoverflow.com/questions/29931477/vsto-outlook-add-in-does-ui-manipulation-need-to-be-done-from-main-thread

https://stackoverflow.com/questions/29315558/vsto-with-windows-form-and-worker-threads/

https://docs.microsoft.com/en-us/visualstudio/vsto/how-to-programmatically-send-e-mail-programmatically?view=vs-2017

https://www.pluralsight.com/guides/how-to-write-your-first-multi-threaded-application-with-c

For Console Application - Processing jobs in a console application

https://docs.hangfire.io/en/latest/background-processing/processing-jobs-in-console-app.html

For ASP.NET

https://www.hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx

https://www.hangfire.io/

https://www.mikesdotnetting.com/article/254/scheduled-tasks-in-asp-net-with-quartz-net

Installing windows service using installutil.exe in visual studio command prompt

Installing windows service using installutil.exe in visual studio command prompt - Dotnet Learners

To install windows service using installutil.exe in visual studio command prompt follow the below steps

To install service:

  • Open visual studio command prompt as run as administrator
  • Type cd %systemroot%\Microsoft.NET\Framework\v4.0.30319\    -> and click enter
    Note: you may need to change the framework version based on VS you have
  • Type installutil SERVICE PATH
  • Example:
    installutil F:\Delete\SampleSolution\Sample\WindowsServiceExample\bin\Debug\WindowsServiceExample.exe

To un install service:

  • Open visual studio command prompt as run as administrator
  • Type cd %systemroot%\Microsoft.NET\Framework\v4.0.30319\    -> and click enter
    Note: you may need to change the framework version based on VS you have
  • Type installutil -u SERVICE PATH
  • Example:
    installutil -u F:\Delete\SampleSolution\Sample\WindowsServiceExample\bin\Debug\WindowsServiceExample.exe

Note:

Instead of opening visual studio command prompt every time and typing all these commands, you can create separate windows command prompt cmd files and open them as run as administrator

Example:

To Install -> install.cmd file:
%systemroot%\Microsoft.NET\Framework\v4.0.30319\installutil F:\Delete\SampleSolution\Sample\WindowsServiceExample\bin\Debug\WindowsServiceExample.exe
pause

Example:

To Un Install -> uninstall.cmd file:
%systemroot%\Microsoft.NET\Framework\v4.0.30319\installutil F:\Delete\SampleSolution\Sample\WindowsServiceExample\bin\Debug\WindowsServiceExample.exe
pause

Categories

Recent posts