Category: .NET

Making any call to a function of an object thread safe

 

 

I was wondering how to modify old code to support threads /task .

So I was making a small project about making any function of an object thread safe.

NuGet Package at : https://www.nuget.org/packages/ThreadSafeObject/

The solution contain tests and 2 console project for .NET Core and .NET Framework 4.5.1

The usage is pretty easy

Let’s say you have this

Calculation c = new Calculation();
c.Add();

And you want

c.Add

to be thread safe

In the Package Manager Console write:

Install-Package ThreadSafeObject

Then modify your code to:

Calculation c = new Calculation();
dynamic ts = new ThreadSafe(c);
ts.Add();

It is a toy project- however, it has tests to prove it is correct.

You can download the code source from https://github.com/ignatandrei/ThreadSafeObject/

Task and generic list

Could you spot the problem in transforming one code that is sequential into a Task ( threaded ) one?

First , this is the sequential one:

 

            var ret = new List<Indicator>();
            var jsonData = await data.JsonData();
            var jo = JArray.Parse(jsonData);
            var page = jo[0].ToObject<Pagination>();
            var array = jo[1].ToObject<Indicator[]>();
            ret.AddRange(array);
            var currentPage = 1;
            while (currentPage < page.pages)
            {
                currentPage++;
                jsonData = await data.JsonData(currentPage);
                jo = JArray.Parse(jsonData);
                array = jo[1].ToObject<Indicator[]>();
                ret.AddRange(array);

            }
            Debug.Assert(ret.Count == page.total, $"{nameof(ret.Count)} : {ret.Count} should be equal {nameof(page.total)} : {page.total}");
            return ret.ToArray();


 

This is the modified with task:

 

            var jsonData = await data.JsonData();
            var jo = JArray.Parse(jsonData);
            var page = jo[0].ToObject<Pagination>();
            var array = jo[1].ToObject<Indicator[]>();
            var ret = new List<Indicator>(array);

            var currentPage = 1;
            var downloads = new List<Task>();
            while (currentPage < page.pages)
            {
                currentPage++;
                var itemPage = currentPage;
                var task = data.JsonData(itemPage)
                    .ContinueWith(it =>
                    {
                        var data = JArray.Parse(it.Result);
                        var pageNr = data[0].ToObject<Pagination>();
                        var indicators = data[1].ToObject<Indicator[]>();
                       ret.AddRange(indicators);

                    }
                );

                downloads.Add(task);
            }
            await Task.WhenAll(downloads);
            Debug.Assert(ret.Count == page.total, $"{nameof(ret.Count)} : {ret.Count} should be equal {nameof(page.total)} : {page.total}");
            return ret.ToArray();

Ok. If you do not know , here is a helper:
Sometimes, at line

 ret.AddRange(indicators)

it gives the error:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. —> System.ArgumentException: Source array was not long enough. Check srcIndex and length, and the array’s lower bounds.
at System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length, Boolean reliable)
at System.Collections.Generic.List`1.set_Capacity(Int32 value)
at System.Collections.Generic.List`1.InsertRange(Int32 index, IEnumerable`1 collection)

Ok. I let you think.
…..
…..
…..
…..
…..
…..
…..
…..
…..
…..
…..
…..
…..
…..
…..
…..
…..
…..
…..
…..
…..
…..
…..
…..
…..
…..
…..
…..

The answer is simple : List < T > is not Thread safe. If you have small quantities of data, does not matter. I was having 16174 records – and sometimes , when multiple threads have come to .AddRange , the internal re-dimensioning of array it does not fulfill the task ( imagine one thread redim to 100, then other 3 threads coming with request of 50+ data)

Solution 1.

Use ConcurrentBag< T > instead of List < T > . This is thread safe and does the trick

Solution 2.
Add to the array in the final of data ( not use ContinueWith) . The code is slightly low performant

           var jsonData = await data.JsonData();
            var jo = JArray.Parse(jsonData);
            var page = jo[0].ToObject<Pagination>();
            var array = jo[1].ToObject<Indicator[]>();
            var ret = new List<Indicator>(array);

            var currentPage = 1;
            var downloads = new List<Task<string>>();
            while (currentPage < page.pages)
            {
                currentPage++;
                var itemPage = currentPage;
                var task = data.JsonData(itemPage);
                downloads.Add(task);
            }
            await Task.WhenAll(downloads);

            foreach (var t in downloads)
            {
                var data = JArray.Parse(t.Result);
                //var pageNr = data[0].ToObject<Pagination>();
                var indicators = data[1].ToObject<Indicator[]>();
                //Console.WriteLine($"reading {pageNr.page} with {item.Length}");
                ret.AddRange(indicators);

            }
            //Console.WriteLine($"total records {ret.Count}");
            Debug.Assert(ret.Count == page.total, $"{nameof(ret.Count)} : {ret.Count} should be equal {nameof(page.total)} : {page.total}");
            return ret.ToArray();

You will find the code at IndicatorRepository in https://github.com/ignatandrei/WorldBankAPi

Maintaining history of data

 

What is this about?

I tend to quote Fowler: “Usually when we see properties on a class, they represent questions we can ask of an object now. However there are times when we don’t want to just ask questions about a property of an object now, we also want to ask these questions about some point in the past when things may have changed. “

For example , we want to track every change that occurs at an Employee ( changing name, salary) and see the previous versions( what was the salary 2 years ago ?)

So what are the software solutions to do an audit log ? First, we should have a history table for each table that we want to maintain an audit log. E.g. Employee => EmployeeHstory

Solution 1 : Coding / Event Sourcing

That means code should maintain history himself – i.e. adding to the history table every modifications.

For Entity Framework this can be done easy, by overiding SaveChanges.

Demo at https://youtu.be/YZ9GDjFApns 

Solution 2 : Table Triggers

This can be done from database . There are triggers for insert , update, delete – and those triggers insert the data in the history table

Demo at https://youtu.be/9xsvCJ-1f7Q

Solution 3, Temporal Tables, Microsot  Sql Server 2016 :

Documentation at https://docs.microsoft.com/en-us/sql/relational-databases/tables/temporal-tables 

Limitations at https://docs.microsoft.com/en-us/sql/relational-databases/tables/temporal-table-considerations-and-limitations 

Demo at https://youtu.be/1Q3DmXJI5h8

Five common mistakes for ASP.NET MVC accesing resources : css, js, images, ajax

This is a Razor /MVC5 variant of older post
http://msprogrammer.serviciipeweb.ro/2010/10/09/five-common-mistakes-for-asp-net-mvc-accesing-resources-css-js-images-ajax/

To have once for all the link to show to people, because too much makes the same error again and again. (From here – you can use ResolveUrl or Url.Content – it’s the same for me. I use ResolveUrl because I used first …)

Case 1 The image does not display

Please check you have the following :

 <img src="@Url.Content("~/Content/images/YOURIMAGE.jpg" )" alt="image" style="border:0" /> or 
 
<img src="~/Content/images/YOURIMAGE.jpg" alt="image" style="border:0" /> 

Case 2 The css does not show

Please check you have the following :

 @string.Format("<link href="{0}" type="text/css" rel="stylesheet" />", Url.Content("~/Content/your.css"))  

or

 <style type="text/css">
@import '@Url.Content("~/Content/your.css")';

</style>  
  <style type="text/css">
<link href='~/Content/your.css' type='text/css' rel='stylesheet' />

</style>  

Case 3 The js does not execute (undefined error)

3.1 Please check you have the following :

 <script type="text/javascript" src="@Url.Content("~/Scripts/yourjs.js")"></script> 

or

 <script type="text/javascript" src="~/Scripts/yourjs.js"></script> 

This should be either in _Layout.cshtml, or in the scripts section

 @section scripts {   } 

in your .cshtml file.
3.2 please check in browser console ( press F12 ) for any javascript error that code may have

Case 4 The js does execute in .cshtml page, but did not execute under js file

Please check you DO NOT have the following @something in the js file. The js file is not interpreted by the same engine as cshtml, so can not interpret asp.net tags. Instead , add a parameter to your function for each @ variable that you have. Simple example : Let’s say in cshtml you have :

 <script type=”text/javascript”>

function Generate(){

window.open('@Url.Action(“About”)’);
}

</script> 

and you call Generate() from .cshtml file. Now you want the same in a .js file. The function Generate will have a parameter instead of Razor variable

 function Generate(url){  window.open(url); } 

and call like this from .cshtml file:

 Generate('@Url.Action("About")'); 

Case 5 The ajax request gives you a 404 error.

Please ensure that you have

 @Url.Content("~/path”) 

and not

 /path 

when you call the Ajax URL

Bonus 1: T4MVC , http://mvccontrib.codeplex.com/releases

Bonus 2: Edit the project file and put <MvcBuildViews>true</MvcBuildViews>

( short url: http://bit.ly/asp5Mistakes)

Async + sync completion + lock

Let’s suppose that you have 2 functions = one true sync and one true async . Let’s suppose more that the sync one can must finish before calling next time ( think about some weird COM component or , in our days, SqlConnection )

If we look just at the async function , we could wait for all. However, the sync function must be called sync

One solution is to make different calls:


var list = new List<Task<int>>(nr);
//add async to list

await Task.WhenAll(list)

//call each sync



But I want to make really async – and one solution is lock

We could wrote the sync function in async manner like this:


//SemaphoreSlim sem = new SemaphoreSlim(1);
static object myObject = new object();
async Task<int> syncTask(int i)         {             
lock (myObject)             
//try{                 
//await sem.WaitAsync();                                 
CallSyncFunction();                             
//}             
//finally             
//{                 
//sem.Release();             
//}                                   
}

The trick that I  used is lock, because the syntax is easier than SemaphoreSlim (BTW: if you want to learn about threading, jump directly to http://www.albahari.com/threading/)
In this manner, the sync function is modified in async -and, more, it waits for completion before entering the second time.

The code is on github on

More details in the Wiki https://github.com/ignatandrei/AsyncSyncLock/wiki or in the code https://github.com/ignatandrei/AsyncSyncLock/

spot errors in VB

Please spot the errors in the following code in VB.NET:

Dim Diff As String = con.ExecuteCommand(“SELECT DATEDIFF(Day, (select [date] from table where Username = ‘” + txtUserName.Text + “‘), ‘” & DateTime.Now.ToString() & “‘)”)
If (Diff > 30) Then
Response.Redirect(“PleaseChangeMyPassword.aspx”)
End If

 

( find at least 3…)

Side note:

No wonder Visual Basic has died ( more or less). Guess future of server javascript ….

Generating Visual Studio solution( or project) references

A Visual Studio pacakge is a plugin of Visual Studio that can do (almost) anything inside Visual Studio

I have made a small project that generates a list of all solution ( or project) references from VS:

 

            foreach (var project in dte.Solution.Projects)
            {
                var p = project as Project;
                if (p == null)
                {
                    continue;
                }

                var vsproject = p.Object as VSLangProj.VSProject;
                if (vsproject == null)
                    continue;

                string nameProject = p.Name;
                foreach (var reference in vsproject.References)
                {
                    var r = reference as Reference;
                    if (r == null)
                        continue;

                    var pathRef = r.Path;

                    //this is a package                    
                    var pa = new PackageAdd();
                  
                    pa.ProjectName = p.Name;
                    pa.IdentifierPackage = r.Identity;
                    pa.VersionPackage = r.Version;
                    pa.NamePackage = r.Name;

                  



                    if (r.SourceProject != null)
                    {
                        
                        pa.NamePackage = r.SourceProject.Name;
                    }
                    sb.AppendLine(pa.ToString());
                }
            }

You can find the solution at https://github.com/ignatandrei/ToolsAndUtilities/tree/master/VS2015/FindReferencesVS

Also the video is at https://youtu.be/a3YHVjJ9fm4

Enjoy!

Thank you for all the API

In our days it is simpler to make an application by putting together some API . I wanted to make a list of all my 5 Minutes .NET playlist videos . First, I have tried to find an application(nothing). Then I have read  You Tube API from https://console.developers.google.com/apis/library . With 2 http requests( one for retrieving all videos from a playlist, the other to find video details) and a NuGet package to export to Excel/Word/PDF/HTML it was simple. You can find the whole project at https://github.com/ignatandrei/YouTube . A video demo at https://www.youtube.com/watch?v=wNHDsHtLBq4 . And the whole list at https://github.com/ignatandrei/ToolsAndUtilities/tree/gh-pages

IDisposable and Marshal.ReleaseCOMObject and dynamic in C#

 

If you have worked with COM, you know that for every COM object that you access is not only necessary to null the reference, but also call Marshall.ReleaseCOMObject .

This is a very error prone task, because you have all try / finally blocks

 
// declare a, ws, w 
try{ 
a=new Application(); 
ws = a.Workbooks; 
w = ws.Add(); 
//code 
}
 catch(...) {
 if( w != null){ 
Marshal.ReleaseComObject(w); 
w = null; 
}
 if(ws !=null){ 
Marshal.ReleaseComObject(ws); 
ws = null; 
} 
if( a!= null) { 
Marshal.ReleaseComObject(a); a= null; 
} 
} 

All of this could be done easy with IDisposable, if

1. IDisposable calls the Marshal.ReleaseCOMObject

2. Find a way to call methods / properties on the COM object from the class that implements IDisposable

 

I have done this and the result is like this:

 
using (dynamic a = new ComDisposable(new Application())) { 
using (dynamic ws = a.Workbooks) { 
using (dynamic w = ws.Add()) { 
using (var shs = w.Sheets) { 
using (var s = shs[1]) { 
//Worksheet a; 
using (var r = a.Range("A1")) { 
r.Value2 = "http://ignatandrei.github.io/ToolsAndUtilities/";; 
using (var f = r.Font) { 
f.Bold = true; 
}
 }
 }
 }
 w.SaveAs(fileName); 
w.Close(); 
} 
}
 a.Quit(); } 

 

Video at https://youtu.be/2qbAcSjL1gU

NuGet package at https://www.nuget.org/packages/ReleaseComObjectDisposable/

AppContext

AppContext is like Application in ASP.NET (MVC). You can see the value all over the application

AppContext.SetSwitch("OCR", true);

And we can have the result in all dll’s by

 public bool IsOCREnabled()
        {
            bool test;
            if (!AppContext.TryGetSwitch("OCR", out test))
                return false;

            return test;
        }

Video demo at https://youtu.be/GMgn4o3yPqw

Andrei Ignat weekly software news(mostly .NET)

* indicates required

Please select all the ways you would like to hear from me:

You can unsubscribe at any time by clicking the link in the footer of our emails. For information about our privacy practices, please visit our website.

We use Mailchimp as our marketing platform. By clicking below to subscribe, you acknowledge that your information will be transferred to Mailchimp for processing. Learn more about Mailchimp's privacy practices here.