Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Tuesday, March 12, 2019

Async calls, why call ConfigureAwait(false)

Adding .ConfigureAwait(false) to your async call takes away the overhead of context switching of threads.

DoSomething();  // on thread 1

await DoMoreAsync().ConfigureAwait(false); // on thread 2

DoSomethingElse();  // continues the work on thread 2 (instead of having to switch to thread 1)

The default for ConfigureAwait is true. But ConfigureAwait(false) is the right thing to do, if  the code following the async all does not rely on the context of thread 1 (thread storage of thread 1, for example).



Async method signature example in C#


Interface

Task<GetDatabaseServersResponse> GetDatabaseServersAsync(GetDatabaseServersRequest request, CancellationToken cancellationToken = default(CancellationToken));

Implementation

public async Task<GetDatabaseServersResponse> GetDatabaseServersAsync(GetDatabaseServersRequest request, CancellationToken cancellationToken = default(CancellationToken))
        {
            var list = await _dbContext.DatabaseServer.ToListAsync(cancellationToken);
            return new GetDatabaseServersResponse(_mapper.Map<List<DatabaseServerRm>>(list), request.TraceId);
        }

Executing an async method synchronously in C#

void NotAnAsyncMethod()
{
try
{
   var answer = someAsyncMethod().GetAwaiter().GetResult();
}
catch (Exception ex)
{
   // ex is our application's exception instead of aggregate exception
   //    aggregate exception is thrown if .Wait() and .Result are used instead
}
}

Thursday, June 15, 2017

Why use async/await pattern?

While code execution is waiting for an IO bound operation, such as SQL or HTTP operation, to complete, the thread that is waiting can be used by other code operations. Basically, mark the method as async and await the results of an IO bound operation. While waiting, the awaited thread can be utilized for other operations.

Friday, October 14, 2016

Building a url with a querystring and encoding values in Url

Encoding/Decoding query parameter values

using System.Web.HttpUtility;

HttpUtility.UrlEncode(s);

HttpUtility.UrlDecode(string str);

Building a url with query string

var queryParms = HttpUtility.ParseQueryString(String.Empty);
queryParms.Add("q", HttpUtility.UrlEncode("books,magazines"));
queryParms.Add("numResults", 1);
UriBuilder ub = new UriBuilder("http://somesite.com/");
ub.Query = queryParms.ToString();
return ub.Uri;

Tuesday, October 11, 2016

Multiple threads with await operator and Task

class Program
{
static void Main(string[] args)
{
StartTaskThreads();
Console.ReadKey();
}

static private async void StartTaskThreads()
{
const int numThreads = 5;
List<Task> tasks = new List<Task>();
for (int i=0; i< numThreads; i++)
tasks.Add(InfiniteTask());

await Task.WhenAll(tasks);
}

static private async Task InfiniteTask()
{
while (true)
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
await Task.Delay(500);
}
}
}

Friday, June 17, 2016

C# run jobs (Task) on multiple threads, return upon completion of the first one

class Program
{
static void Main(string[] args)
{
Test();
Console.ReadKey();
}

static async void Test()
{
int result = await TaskTest();
Console.WriteLine(result);
}
static async Task<int> TaskTest()
{
Task<int> task1 = new Task<int>(() => { Thread.Sleep(1000); return 1; });
Task<int> task2 = new Task<int>(() => { Thread.Sleep(50); return 2; });
task1.Start();
task2.Start();
var multiTaskResult = await Task.WhenAny(task1, task2);
return multiTaskResult.Result;
}
}

Sunday, April 24, 2016

C# DateTime vs DateTimeOffset

DateTimeOffset is similar to DateTime except it allows explicit specification of "offset" of the date time from UTC.

CODE

DateTime dateTime = new DateTime(2016, 4, 22, 0, 0, 0, DateTimeKind.Unspecified);            Debug.WriteLine(DateTimeKind.Unspecified.ToString() + ": " + dateTime.ToString("o"));
            // json serialize applies ToString("o")
            Debug.WriteLine("Json Serialize: " + Newtonsoft.Json.JsonConvert.SerializeObject(dateTime));

            DateTime dateTimeUTC = new DateTime(2016, 4, 22, 0, 0, 0, DateTimeKind.Utc);
            Debug.WriteLine(DateTimeKind.Utc.ToString() + ": " + dateTimeUTC.ToString("o"));
            Debug.WriteLine("Json Serialize: " + Newtonsoft.Json.JsonConvert.SerializeObject(dateTimeUTC));

            DateTime dateTimeLocal = new DateTime(2016, 4, 22, 0, 0, 0, DateTimeKind.Local);
            Debug.WriteLine(DateTimeKind.Local.ToString() + ": " + dateTimeLocal.ToString("o"));
            Debug.WriteLine("Json Serialize: " + Newtonsoft.Json.JsonConvert.SerializeObject(dateTimeLocal));

            DateTime dateTimeLocalNow = DateTime.Now;
            Debug.WriteLine(dateTimeLocalNow.Kind.ToString() + ": " + dateTimeLocalNow.ToString("o"));
            Debug.WriteLine("Json Serialize: " + Newtonsoft.Json.JsonConvert.SerializeObject(dateTimeLocalNow));

            DateTimeOffset dateTimeOffsetNoOffset = new DateTimeOffset(2016, 4, 22, 0, 0, 0, new TimeSpan());
            Debug.WriteLine("No offset: " + dateTimeOffsetNoOffset.ToString("o"));
            Debug.WriteLine("Json Serialize: " + Newtonsoft.Json.JsonConvert.SerializeObject(dateTimeOffsetNoOffset));

            DateTimeOffset dateTimeOffsetUTC = new DateTimeOffset(2016, 4, 22, 0, 0, 0, new TimeSpan(0, 0, 0));
            Debug.WriteLine("Zero offset: " + dateTimeOffsetUTC.ToString("o"));
            Debug.WriteLine("Json Serialize: " + Newtonsoft.Json.JsonConvert.SerializeObject(dateTimeOffsetUTC));

            DateTimeOffset dateTimeOffsetSpecified = new DateTimeOffset(2016, 4, 22, 0, 0, 0, new TimeSpan(-7, 0, 0));
            Debug.WriteLine("Specified offset: " + dateTimeOffsetSpecified.ToString("o"));
            Debug.WriteLine("Json Serialize: " + Newtonsoft.Json.JsonConvert.SerializeObject(dateTimeOffsetSpecified));

            DateTimeOffset dateTimeOffsetLocalNow = DateTimeOffset.Now;
            Debug.WriteLine("Local offset: " + dateTimeOffsetLocalNow.ToString("o"));
            Debug.WriteLine("Json Serialize: " + Newtonsoft.Json.JsonConvert.SerializeObject(dateTimeOffsetLocalNow));

            DateTimeOffset dateTimeOffsetUtcNow = DateTimeOffset.UtcNow;
            Debug.WriteLine("Utc offset: " + dateTimeOffsetUtcNow.ToString("o"));
            // json serialize applies ToString("o")
            Debug.WriteLine("Json Serialize: " + Newtonsoft.Json.JsonConvert.SerializeObject(dateTimeOffsetUtcNow));

OUTPUT

Unspecified: 2016-04-22T00:00:00.0000000
Json Serialize: "2016-04-22T00:00:00"

Utc: 2016-04-22T00:00:00.0000000Z
Json Serialize: "2016-04-22T00:00:00Z"

Local: 2016-04-22T00:00:00.0000000-07:00
Json Serialize: "2016-04-22T00:00:00-07:00"

Local: 2016-04-24T12:18:09.1892907-07:00
Json Serialize: "2016-04-24T12:18:09.1892907-07:00"

No offset: 2016-04-22T00:00:00.0000000+00:00
Json Serialize: "2016-04-22T00:00:00+00:00"

Zero offset: 2016-04-22T00:00:00.0000000+00:00
Json Serialize: "2016-04-22T00:00:00+00:00"

Specified offset: 2016-04-22T00:00:00.0000000-07:00
Json Serialize: "2016-04-22T00:00:00-07:00"

Local offset: 2016-04-24T12:18:09.1892907-07:00
Json Serialize: "2016-04-24T12:18:09.1892907-07:00"

Utc offset: 2016-04-24T19:18:09.1892907+00:00
Json Serialize: "2016-04-24T19:18:09.1892907+00:00"

Wednesday, February 24, 2016

Building responsive WPF UI using async, await and Task class

async void btnRun_Click(object sender, RoutedEventArgs e)
{
this.txtStatus.Text = "Running...";
this.btnRun.IsEnabled = false;

try
{
// create and queue the Task to be completed on another thread
//   and wait for it to be completed
//   while keeping the UI responsive
  // await manages retrieval of results from the completed Task
string result = await Task.Run<string>(
() =>
{
Thread.Sleep(3000);
// throw new Exception("Something went wrong");
return "Done!";
});

this.txtStatus.Text = result;
}
catch (Exception ex)
{
this.txtStatus.Text = ex.Message;
}

this.btnRun.IsEnabled = true;
}

Wednesday, February 3, 2016

ASP.NET MVC: Creating and downloading MS Excel File

 #region Controller Action
public ActionResult Index()
{
// Download link displayed on this view
//<h2>@Html.ActionLink("Download", "Download")</h2>
return View();
}


public ActionResult Download()
{
var data = new List<DataRow>
{
new DataRow{Date = DateTime.Now, Amount = 1M, Note = "Good, one"},
new DataRow{Date = DateTime.Now, Amount = 2M}
};

string reportName = "SampleReport_" + DateTime.Now.ToString();
string reportNameCleansed = RemoveInvalidChars(reportName);
return File(Encoding.UTF8.GetBytes(GetCSVReportData(data)),
"application/text", reportNameCleansed + ".csv");
}
#endregion


#region Helpers
class DataRow
{
public DateTime Date { get; set; }
public Decimal Amount { get; set; }
public string Note { get; set; }
}


string RemoveInvalidChars(string fileName)
{
string ret = string.Empty;

foreach (char c in System.IO.Path.GetInvalidFileNameChars())
{
ret = fileName.Replace(c, '-');
}
return ret;
}


string GetCSVReportData(List<DataRow> data)
{
var fileData = new StringBuilder();
fileData.AppendLine("Date,Amount,Note");
foreach (var item in data)
  {
fileData.AppendFormat("{0},{1},\"{2}\"",
item.Date.ToString("yyyy-MM-dd"),
item.Amount.ToString("########0.0000"),
item.Note);
fileData.AppendLine();
}
return fileData.ToString();
}
#endregion

Wednesday, November 25, 2015

CachedData helper class using .Net MemoryCache

 static public class CachedData
{
    const int DEFAULT_CACHE_TIME_SECONDS = 60;
 
    // helper method
    static private T Get<T>(string key, Func<T> retriever, int cachedTimeInSeconds) where T : class
    {
        var cacheItem = MemoryCache.Default.GetCacheItem(key);
        if (cacheItem == null)
        {
            T data = retriever();
            MemoryCache.Default.Set(key, data, new CacheItemPolicy()
            {
                AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(cachedTimeInSeconds)
            });
            return data;
        }
        else
        {
            return (cacheItem.Value as T);
        }
    }
 
    //  Cached data item
    static public List<string> GetMyDataList()
    {
        // define a function that retrieves data
        //   if data is not already present in cache
     
        Func<List<String>> retriever = () =>
        {
            var data = new List<string>();
            // TODO: retrieve and set data from storage
            return data;
        };
        return Get<List<string>>("MY_DATA_LIST_KEY",
            retriever, DEFAULT_CACHE_TIME_SECONDS);
    }
 
    // define methods for other cached data items
}


// accessing the cache data
var myDataList = CachedData.GetMyDataList();

Tuesday, August 4, 2015

How to use IEnumerable (generate Fibonacci numbers)?

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Fib
{
    class Program
    {
        static void Main(string[] args)
        {
            Debug.WriteLine(EvenFibLessThan(40000));
        }


        static int EvenFibLessThan(int maxFibNumber)
        {
            int ret = 0;
            int lastEven = 0;
            foreach (var i in fibEnumerator())
            {
                Debug.WriteLine(i);
                if (i % 2 == 0)
                {
                    if (i > maxFibNumber)
                        return lastEven;
                    lastEven = i;
                }
            }
            return ret;
        }

        static IEnumerable<int> fibEnumerator()
        {
            int last = 1;
            yield return last;

            int current = 1;
            yield return current;

            while (true)
            {
                int next = last + current;
                last = current;
                current = next;
                yield return current;
            }
        }
    }
}

Tuesday, July 14, 2015

Generate a random number


static public class Utility
    {
        static Random _rnd;

        static Utility()
        {
              // we need to keep an instance of Random around
              // so that we get a different number on each subsequent call
            _rnd = new Random(Environment.TickCount);
        }

        static public string GetRandomNumber()
        {
            return _rnd.Next(100000, 999999).ToString();
        }
    }

Monday, June 8, 2015

Using Entity Framework with pre-existing database tables

Given

  • A pre-existing database called Inventory
  • A table named Product in the database

Objective

Access the Product table using entity framework

Steps

  1. Create a console application
  2. Install EntityFramework package using Nuget
  3. Add the connection string to App.config
<connectionStrings>
    <add name="InventoryDbContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=Inventory;Integrated Security=True;Pooling=False"
         providerName ="System.Data.SqlClient"/>
  </connectionStrings>

Code

// Class for accessing the rows in the table
// EF would normally look for "Products" table
// Tell EF to look for "Product" table
[Table("Product")]      
public class Product
{
  public int Id { get; set; }
  public string PartNumber { get; set; }
  public string PartName { get; set; }
}

// database context for access
public class InventoryDbContext : DbContext
{
  static InventoryDbContext()
  {
    // Turn off EF's database initialization (our database is pre-existing)
    Database.SetInitializer<InventoryDbContext>(null);
  }
  // Set with access to rows in the Product table
  public IDbSet<Product> Products { get; set; }
}

class Program
{
  
  static void Main(string[] args)
  {
    using (var ctx = new InventoryDbContext())
    {
      var products = ctx.Products.ToList();
      products.ForEach(p => 
        Console.WriteLine("{0}: {1}, {2}", p.Id, p.PartNumber, p.PartName));
    }
    Console.ReadKey();
  }
}

Output

1: 0001, Widget
2: 0002, Binder
3: 0003, Marker

Sunday, June 7, 2015

Using Moq for Unit Testing


What is it?

  • Generate objects (instances) based on interfaces
  • Declaratively define the behavior of generated object
  • Use Nuget to add Moq to your project

Example

  • We want to unit test the invoice class.
  • We want to "fix" the behavior of shipping and tax calculation classes so that we can truly exercise and test the functionality of invoice class in isolation

Code to Test


public class Invoice
    {
        IShippingCalc _shippingCalc;
        ITaxCalc _taxCalc;
        decimal _subTotal;
        string _state;

        public Invoice(decimal subTotal, string state, IShippingCalc shippingCalc,
            ITaxCalc taxCalc)
        {
            this._state = state;
            this._shippingCalc = shippingCalc;
            this._taxCalc = taxCalc;
            this._subTotal = subTotal;
        }
        public decimal TotalDue
        {
            get
            {
                return _subTotal + _shippingCalc.Calc(_state) + _taxCalc.CalcTax(_state, _subTotal);
            }
        }
    }

    public interface IShippingCalc
    {
        decimal Calc(string state);
    }

    public interface ITaxCalc
    {
        decimal CalcTax(string state, decimal taxableAmount);
    }

Unit Test


  • We create "mocks" for IShippingCalc and ITaxCalc using Moq
  • We define the behavior of these mocked objects so that we can verify the behavior of the invoice class

public void BasicInvoiceTest()
{
var shippingMoq = new Mock<IShippingCalc>();
shippingMoq.Setup(
m => m.Calc(
It.Is<string>(state => 
state.Equals("ca", StringComparison.InvariantCultureIgnoreCase)))).Returns(5);
shippingMoq.Setup(
  m => m.Calc(
  It.Is<string>(state =>
  !state.Equals("ca", StringComparison.InvariantCultureIgnoreCase)))).Returns(10);

var taxMoq = new Mock<ITaxCalc>();
taxMoq.Setup(   // no sales tax for other states
m => m.CalcTax(It.IsAny<String>(), It.IsAny<decimal>()))
.Returns<string, decimal>((s, d) => 0);

taxMoq.Setup(   // 8% sales tax for CA
m => m.CalcTax(It.IsIn("ca", "CA", "Ca", "ca"), It.IsAny<decimal>()))
.Returns((string state, decimal taxableAmount) => taxableAmount * .08M);

var subTotal = 100;
var invoiceCA = new Invoice(subTotal, "ca", shippingMoq.Object, taxMoq.Object);
Assert.AreEqual((100 + 8 + 5), invoiceCA.TotalDue, "subTotal + Sales Tax + $5 shipping");

var invoiceOther = new Invoice(subTotal, "ma", shippingMoq.Object, taxMoq.Object);
Assert.AreEqual((100 + 0 + 10), invoiceOther.TotalDue, "subTotal + NO Tax + $10 shipping");
}

Saturday, June 6, 2015

Using Unity IOC Container for Dependency Injection


What is it?

  • Unity is an IOC container for .NET
  • Unity can be installed in any .NET project using Nuget

Usage Example


using System;
using Microsoft.Practices.Unity;

namespace IOCUnityTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create the container for objects
            UnityContainer unityContainer = new UnityContainer();

            // Tell container how to resolve types
            unityContainer.RegisterType<IProducts, Products>();
            unityContainer.RegisterType<IShipping, FixedShipping>(
                new ContainerControlledLifetimeManager());  // singleton

            // Have the container create an instance of invoice
            var invoice1 = unityContainer.Resolve<Invoice>();
            Console.WriteLine("Invoice 1 Total: " + invoice1.Total);

            // Change what IShipping resolves to (FreeShipping)
            unityContainer.RegisterType<IShipping, FreeShipping>();
            var invoice2 = unityContainer.Resolve<Invoice>(); 
            Console.WriteLine("Invoice 2 Total: " + invoice2.Total);
        }
    }

    interface IProducts
    {
        decimal SubTotal { get; set; }
    }

    interface IShipping
    {
        decimal ShippingCharge { get; set; }
    }

    class Products : IProducts
    {
        public decimal SubTotal
        {
            get
            {
                return 10;
            }
            set { }
        }
    }

    class FixedShipping : IShipping
    {
        public decimal ShippingCharge
        {
            get
            {
                return 5;
            }
            set { }
        }
    }

    class FreeShipping : IShipping
    {
        public decimal ShippingCharge
        {
            get
            {
                return 0;
            }
            set { }
        }
    }

    class Invoice
    {
        IProducts _products;
        IShipping _shipping;
        public Invoice(IProducts products, IShipping shipping)
        {
            this._products = products;
            this._shipping = shipping;
        }

        public decimal Total
        {
            get
            {
                return this._products.SubTotal + this._shipping.ShippingCharge;
            }
        }
    }
}

Friday, June 5, 2015

Selecting an index based on hashed value of data

Background

Let's say we have 5 resources. We want to select one of these resources based on the incoming data (key).

String[] resources = new String[]
{
"Server 1",
"Server 2",
"Server 3",
"Server 4",
"Server 5"
};

Helper Methods


// returns an index based on a key
static int SelectIndex(String key, int totalIndices)
{
return (int)(GetInt64HashCode(key) % (ulong)totalIndices);
}

// helper method to calculate a numeric hash for a string
static UInt64 GetInt64HashCode(string str)
{
UInt64 hashedValue = UInt64.MaxValue / UInt32.MaxValue;
 UInt64 hashedValueMultiplier = UInt64.MaxValue / UInt16.MaxValue;
for (int i = 0; i < str.Length; i++)
{
hashedValue += str[i];
hashedValue *= hashedValueMultiplier;
}
return hashedValue;
}

Test

{
"Server 1",
"Server 2",
"Server 3",
"Server 4",
"Server 5"
};

Dictionary<int, int> selectionDistribution = new Dictionary<int, int>();
for (int i=0; i<resources.Length; i++)
{
selectionDistribution.Add(i, 0);
}

int keyCount = 10000;
for (int i = 0; i < keyCount; i++)
{
String key = Guid.NewGuid().ToString();
int selectedIndex = SelectIndex(key, resources.Length);
selectionDistribution[selectedIndex] = ++selectionDistribution[selectedIndex];
Console.WriteLine("{0} goes to {1}", key, resources[selectedIndex]);
}

Console.WriteLine("*** Distribution ***");
foreach(KeyValuePair<int, int> pair in selectionDistribution)
{
Console.WriteLine("{0}: {1}", resources[pair.Key], pair.Value);
}
Console.ReadKey();

Output

21b33e71-9bb6-49c9-a8f1-b435a0896596 goes to Server 3
9453c55f-409c-45f0-9941-fc5623c8d5da goes to Server 4
e26eef17-e357-4c22-b546-9a9a3329fc5b goes to Server 1
f2a516d6-5bed-4736-abad-e508d77d1c12 goes to Server 1
0fe01f0d-1860-4358-80ab-c7f27ab400ca goes to Server 4
.....
....
704441d5-7f2f-444a-90ea-60478fcebb85 goes to Server 4
c2b7ec3f-2d48-49f2-aa0d-541ea6c464d4 goes to Server 3
1fc81dce-4e5b-41b7-bd49-fe9abefffcda goes to Server 1
*** Distribution ***
Server 1: 2036
Server 2: 1962
Server 3: 1986
Server 4: 2035
Server 5: 1981

Friday, May 1, 2015

Object caching in .Net with MemoryCache class

.Net 4.0 implements MemoryCache class to facilitate caching of frequently used data in any application built with .Net.

Assembly Reference: System.Runtime.Caching.dll

// using the default instance of MemoryCache in this example
// default cache is Global to the application
ObjectCache _defaultCache = MemoryCache.Default;

// Alternatively, we can create and use custom instance of MemoryCache
// const String CUSTOM_CACHE_NAME = "MyCache";
// ObjectCache customCache = new MemoryCache(CUSTOM_CACHE_NAME);

 // eviction and expiration details for a specific cache entry.
CacheItemPolicy policy = new CacheItemPolicy()
{
// used to determine whether to evict a cache entry
// Priority = CacheItemPriority.NotRemovable,
Priority = CacheItemPriority.Default,

// whether a cache entry should be evicted if it has not been accessed in a given span of time.
SlidingExpiration = TimeSpan.FromMinutes(30),

// Other options
// indicates whether a cache entry should be evicted after a specified duration.
// AbsoluteExpiration = DateTimeOffset.Now.AddHours(1),

//  a collection of ChangeMonitor objects that are associated with a cache entry.
// ChangeMonitors = ...

// a reference to a CacheEntryRemovedCallback delegate that is called after an entry is removed from the cache.
// RemovedCallback = ...

// a reference to a CacheEntryUpdateCallback delegate that is called before a cache entry is removed from the cache
// UpdateCallback = ...
};

// an individual entry in the cache
CacheItem item = new CacheItem(
key: Guid.NewGuid().ToString(),
value: DateTime.UtcNow
);

// true if insertion succeeded, or false if there is an already an entry in the cache that has the same key as item
var insertionSucceededBecauseNoneExistedBefore = _defaultCache.Add(item, policy);

// If a cache entry with the same key exists, the existing cache entry; otherwise, null.
var existingItemIfAnyOrNullIfNoneExistedBefore = _defaultCache.AddOrGetExisting(item, policy);

// the Set method always puts a cache value in the cache, regardless whether an entry already exists that has the same key
_defaultCache.Set(item, policy);

// A reference to the cache entry identified by key if the entry exists; otherwise, null.
var cachedItemIfAny = _defaultCache.GetCacheItem(item.Key);

// iterate through all cached items
StringBuilder sb = new StringBuilder();
foreach(var item in _defaultCache)
{
sb.AppendLine(item.Key + "= " + item.Value);
}

Monday, April 6, 2015

An Interval Timer Class - Performing a task at regular intervals

Sometimes you need to do certain tasks at regular intervals such as logging or publishing metrics. Instead of littering your code with repeated checks whether desired time has passed, we can encapsulate this logic in a simple class IntervalTimer.

Helper Class

public class IntervalTimer
{
DateTime _lastCheckpoint;
TimeSpan _tripInterval;

public IntervalTimer(TimeSpan tripInterval)
{
_lastCheckpoint = DateTime.UtcNow;
_tripInterval = tripInterval;
}

public bool IsTripped
{
get
{
return DateTime.UtcNow > 
              _lastCheckpoint.Add(_tripInterval);
}
}

public void Reset()
{
_lastCheckpoint = DateTime.UtcNow;
}
}

Usage

// initialize a timer that trips every minute
var intervalTimer = new IntervalTimer(TimeSpan.FromMinutes(1));

// this code should probably be run on a separate thread
//   especially for a GUI application
while(true)
{
if (intervalTimer.IsTripped)
{
// Do your thing here (log, publish metrics, etc.)

intervalTimer.Reset();
}
Thread.Sleep(1000);
}

Saturday, February 14, 2015

Parallel Programming with Task Class

Run a long running operation on another thread

// waits for the task to complete because of "await" keyword
// control returns to the caller method while task executes
// code following Task.Run() executes after the task completes

// this is ideal for executing code from "click" 
// and event handlers in a GUI application for a
// responsive user experience

int retVal = await Task.Run(
() => 
{
// long running operation
return 1; 
}
);

Run two long running operations one after the other on another thread

// note how the second task uses the result from first task
retVal = await Task.Run(
() => { return 1;  }
).ContinueWith(t => { return 1 + t.Result; });

Communicate cancellation request to a Task

static CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
static CancellationToken cancellationToken = cancellationTokenSource.Token;

int retVal = await Task.Run(
() => 
{
// long running operation
if (cancellationToken.IsCancellationRequested)
     // OperationCanceledException is caught by the method
     // running the task and shown to user
cancellationToken.ThrowIfCancellationRequested();
return 1; 
}, cancellationToken
);

To cancel:
CancellationTokenSource.Cancel();

Report Progress


//  This lambda will be run on the UI thread.
var progress = new Progress<string>(msg =>
{
  textBox.Text = msg;
});


// "progress" is passed as IProgress<string> progress to the
// long running method so that
// it can report progress

Block execution until a task completes

Task<int> task = Task.Run(
() =>
{
// long running operation
return 1;
}
);

// Halt further execution until the task completes
Task.WaitAll(task);

// See the "await" examples above. With "await" the execution
// returns to the caller while a task runs