Is there any low level metric/logging of thread locks in .NET? - c#

Over the years, I've not really come across this if it exists, so I'm putting this out there to understand if anyone knows of any low-level .NET functionality, maybe within reflection, that can capture when a thread has become locked? Some kind of logging perhaps?
private object _lockObject = new object();
void MyFunc()
{
lock(_lockObject) // <== How can I understand how many threads are waiting on this?
{
// Do work
}
}
Is it workable to put together some kind of lock handler and pass it a predicate such as...?
void DoLock(object lockObject, Action predicate)
{
push(threadid);
lock(lockObject)
{
pop(threadid);
predicate();
}
}

You can get some information via PerformanceCounter.
In order to do this, you will need to know the name of the process that you want to monitor.
The performance counter category name is ".NET CLR LocksAndThreads", and the counter names for that category are shown in the table on the page I linked above.
The monitoring is typically performed from a different process than the one being monitored, but for simplicity here is a sample console application that monitors itself:
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main()
{
var counter1 = new PerformanceCounter(".NET CLR LocksAndThreads", "Contention Rate / sec", "ConsoleApp1");
var counter2 = new PerformanceCounter(".NET CLR LocksAndThreads", "Total # of Contentions", "ConsoleApp1");
Task.Run(() => test());
Task.Run(() => test());
Task.Run(() => test());
Task.Run(() => test());
while (true)
{
Thread.Sleep(100);
Console.WriteLine($"Contention: {counter1.NextValue()}/sec, Total: {counter2.NextValue()}");
}
}
static object locker = new object();
static void test()
{
while (true)
{
lock (locker)
{
Thread.Sleep(50);
}
}
}
}
}

Related

How to unit test code that should execute only once in a MultiThread scenario?

A class contains an attribute that should be created only one time. The creation process is via a Func<T> which is pass in argument. This is a part of a caching scenario.
The test take care that no matter how many threads try to access the element, the creation occurs only once.
The mechanism of the unit test is to launch a great number of threads around the accessor, and count how many times the creation function is called.
This is not deterministic at all, nothing guaranteed that this is effectively testing a multithread access. Maybe there will be only one thread at a time that will hit the lock. (In reality, getFunctionExecuteCount is between 7 and 9 if the lock is not there... On my machine, nothing guaranteed that on the CI server it's going to be the same)
How the unit test can be rewritten in a deterministic way? How to be sure that the lock is triggered multiple times by multiple thread?
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Example.Test
{
public class MyObject<T> where T : class
{
private readonly object _lock = new object();
private T _value = null;
public T Get(Func<T> creator)
{
if (_value == null)
{
lock (_lock)
{
if (_value == null)
{
_value = creator();
}
}
}
return _value;
}
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void MultipleParallelGetShouldLaunchGetFunctionOnlyOnce()
{
int getFunctionExecuteCount = 0;
var cache = new MyObject<string>();
Func<string> creator = () =>
{
Interlocked.Increment(ref getFunctionExecuteCount);
return "Hello World!";
};
// Launch a very big number of thread to be sure
Parallel.ForEach(Enumerable.Range(0, 100), _ =>
{
cache.Get(creator);
});
Assert.AreEqual(1, getFunctionExecuteCount);
}
}
}
The worst scenario is if someone break the lock code, and the testing server had some lag. This test shouldn't pass:
using NUnit.Framework;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Example.Test
{
public class MyObject<T> where T : class
{
private readonly object _lock = new object();
private T _value = null;
public T Get(Func<T> creator)
{
if (_value == null)
{
// oups, some intern broke the code
//lock (_lock)
{
if (_value == null)
{
_value = creator();
}
}
}
return _value;
}
}
[TestFixture]
public class UnitTest1
{
[Test]
public void MultipleParallelGetShouldLaunchGetFunctionOnlyOnce()
{
int getFunctionExecuteCount = 0;
var cache = new MyObject<string>();
Func<string> creator = () =>
{
Interlocked.Increment(ref getFunctionExecuteCount);
return "Hello World!";
};
Parallel.ForEach(Enumerable.Range(0, 2), threadIndex =>
{
// testing server has lag
Thread.Sleep(threadIndex * 1000);
cache.Get(creator);
});
// 1 test passed :'(
Assert.AreEqual(1, getFunctionExecuteCount);
}
}
}
To make it deterministic, you only need two threads and ensure one of them blocks inside the function, while the other tries to get inside as well.
[TestMethod]
public void MultipleParallelGetShouldLaunchGetFunctionOnlyOnce()
{
var evt = new ManualResetEvent(false);
int functionExecuteCount = 0;
var cache = new MyObject<object>();
Func<object> creator = () =>
{
Interlocked.Increment(ref functionExecuteCount);
evt.WaitOne();
return new object();
};
var t1 = Task.Run(() => cache.Get(creator));
var t2 = Task.Run(() => cache.Get(creator));
// Wait for one task to get inside the function
while (functionExecuteCount == 0)
Thread.Yield();
// Allow the function to finish executing
evt.Set();
// Wait for completion
Task.WaitAll(t1, t2);
Assert.AreEqual(1, functionExecuteCount);
Assert.AreEqual(t1.Result, t2.Result);
}
You may want to set a timeout on this test :)
Here's a variant allowing to test more cases:
public void MultipleParallelGetShouldLaunchGetFunctionOnlyOnce()
{
var evt = new ManualResetEvent(false);
int functionExecuteCount = 0;
var cache = new MyObject<object>();
Func<object> creator = () =>
{
Interlocked.Increment(ref functionExecuteCount);
evt.WaitOne();
return new object();
};
object r1 = null, r2 = null;
var t1 = new Thread(() => { r1 = cache.Get(creator); });
t1.Start();
var t2 = new Thread(() => { r2 = cache.Get(creator); });
t2.Start();
// Make sure both threads are blocked
while (t1.ThreadState != ThreadState.WaitSleepJoin)
Thread.Yield();
while (t2.ThreadState != ThreadState.WaitSleepJoin)
Thread.Yield();
// Let them continue
evt.Set();
// Wait for completion
t1.Join();
t2.Join();
Assert.AreEqual(1, functionExecuteCount);
Assert.IsNotNull(r1);
Assert.AreEqual(r1, r2);
}
If you want to delay the second call, you won't be able to use Thread.Sleep, as it'll cause the thread to go to the WaitSleepJoin state:
The thread is blocked. This could be the result of calling Thread.Sleep or Thread.Join, of requesting a lock — for example, by calling Monitor.Enter or Monitor.Wait — or of waiting on a thread synchronization object such as ManualResetEvent.
And we won't be able to tell if the thread is sleeping or waiting on your ManualResetEvent...
But you can easily substitute the sleep with a busy wait. Comment out the lock, and change t2 to:
var t2 = new Thread(() =>
{
var sw = Stopwatch.StartNew();
while (sw.ElapsedMilliseconds < 1000)
Thread.Yield();
r2 = cache.Get(creator);
});
Now the test will fail.
I don't think a really deterministic way exists, but you can raise the probability so that it's very difficult to not cause concurrent races:
Interlocked.Increment(ref getFunctionExecuteCount);
Thread.Yield();
Thread.Sleep(1);
Thread.Yield();
return "Hello World!";
By raising the Sleep() parameter (to 10?) it gets more and more improbable that no concurrent race takes place.
In addition to pid's answer:
This code doesn't actually create a lot of threads.
// Launch a very big number of thread to be sure
Parallel.ForEach(Enumerable.Range(0, 100), _ =>
{
cache.Get(creator);
});
It will start ~Environment.ProcessorCount threads. More details.
If you want to get a lot of threads you should do it explicitly.
var threads = Enumerable.Range(0, 100)
.Select(_ => new Thread(() => cache.Get(creator))).ToList();
threads.ForEach(thread => thread.Start());
threads.ForEach(thread => thread.Join());
So if you will have enough threads and you will enforce them to switch you will get concurrent race.
If you care about case when your CI server will have only one free core, you can include this constraint in your test by changing Process.ProcessorAffinity property. More details.

How to specify the number of parallel tasks executed in Parallel.ForEach? [duplicate]

This question already has answers here:
Keep running a specific number of tasks
(2 answers)
Have a set of Tasks with only X running at a time
(5 answers)
Closed 9 years ago.
I have ~500 tasks, each of them takes ~5 seconds where most of the time is wasted on waiting for the remote resource to reply. I would like to define the number of threads that should be spawned myself (after some testing) and run the tasks on those threads. When one task finishes I would like to spawn another task on the thread that became available.
I found System.Threading.Tasks the easiest to achieve what I want, but I think it is impossible to specify the number of tasks that should be executed in parallel. For my machine it's always around 8 (quad core cpu). Is it possible to somehow tell how many tasks should be executed in parallel? If not what would be the easiest way to achieve what I want? (I tried with threads, but the code is much more complex). I tried increasing MaxDegreeOfParallelism parameter, but it only limits the maximum number, so no luck here...
This is the code that I have currently:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
private static List<string> _list = new List<string>();
private static int _toProcess = 0;
static void Main(string[] args)
{
for (int i = 0; i < 1000; ++i)
{
_list.Add("parameter" + i);
}
var w = new Worker();
var w2 = new StringAnalyzer();
Parallel.ForEach(_list, new ParallelOptions() { MaxDegreeOfParallelism = 32 }, item =>
{
++_toProcess;
string data = w.DoWork(item);
w2.AnalyzeProcessedString(data);
});
Console.WriteLine("Finished");
Console.ReadKey();
}
static void Done(Task<string> t)
{
Console.WriteLine(t.Result);
--_toProcess;
}
}
class Worker
{
public string DoWork(string par)
{
// It's a long running but not CPU heavy task (downloading stuff from the internet)
System.Threading.Thread.Sleep(5000);
return par + " processed";
}
}
class StringAnalyzer
{
public void AnalyzeProcessedString(string data)
{
// Rather short, not CPU heavy
System.Threading.Thread.Sleep(1000);
Console.WriteLine(data + " and analyzed");
}
}
}
Assuming you can use native async methods like HttpClient.GetStringAsync while getting your resource,
int numTasks = 20;
SemaphoreSlim semaphore = new SemaphoreSlim(numTasks);
HttpClient client = new HttpClient();
List<string> result = new List<string>();
foreach(var url in urls)
{
semaphore.Wait();
client.GetStringAsync(url)
.ContinueWith(t => {
lock (result) result.Add(t.Result);
semaphore.Release();
});
}
for (int i = 0; i < numTasks; i++) semaphore.Wait();
Since GetStringAsync uses IO Completions Ports internally (like most other async IO methods) instead of creating new threads, this can be the solution you are after.
See also http://blog.stephencleary.com/2013/11/there-is-no-thread.html
As L.B mentioned, .NET Framework has methods that performs I/O operations (requests to databases, web services etc.) using IOCP internally, they can be recognized by their names - it ends with Async by convention. So you could just use them to build robust scalable applications that can process multiple requests simultaneously.
EDIT: I've completely rewritten the code example with the modern best practices so it becomes much more readable, shorter and easy to use.
For the .NET 4.5 we can use async-await approach:
class Program
{
static void Main(string[] args)
{
var task = Worker.DoWorkAsync();
task.Wait(); //stop and wait until our async method completed
foreach (var item in task.Result)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
}
static class Worker
{
public async static Task<IEnumerable<string>> DoWorkAsync()
{
List<string> results = new List<string>();
for (int i = 0; i < 10; i++)
{
var request = (HttpWebRequest)WebRequest.Create("http://microsoft.com");
using (var response = await request.GetResponseAsync())
{
results.Add(response.ContentType);
}
}
return results;
}
}
Here is the nice MSDN tutorial about async programming using async-await.

Can't reproduce threading deadlock with MethodImplOptions.Synchronized

I'm trying to reproduce some deadlock with only MethodImplOptions.Synchronized method notation:
using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
namespace Lab_01
{
class Program1
{
[MethodImpl(MethodImplOptions.Synchronized)]
static void Resource1(int starterIndex, bool startNext = true)
{
Console.WriteLine("Resource1 is used ({0})", starterIndex);
Thread.Sleep(1000);
if (startNext)
{
Resource2(starterIndex, false);
}
Console.WriteLine("Resource1 is free ({0})", starterIndex);
}
[MethodImpl(MethodImplOptions.Synchronized)]
static void Resource2(int starterIndex, bool startNext = true)
{
Console.WriteLine("Resource2 is used ({0})", starterIndex);
Thread.Sleep(1000);
if (startNext)
{
Resource1(starterIndex, false);
}
Console.WriteLine("Resource2 is free ({0})", starterIndex);
}
static void Main(string[] args)
{
Locker locker1 = new Locker();
Locker locker2 = new Locker();
new Thread(delegate()
{
Resource1(0);
}).Start();
new Thread(delegate()
{
Resource2(1);
}).Start();
}
}
}
What I expect is
1st thread is started and only the Resource1 method is locked, it waits for 1 sec
While 1st thread is sleeping (this 1 second) 2nd thread is started and it locks the 2nd resource (Resource2). It sleeps for 1 sec.
The thread, which ends the sleep first, say 1st thread, want to lock the 2nd resource, but it can't because it's already locked, and can't be freed, because the second thread is in the same situation (it wants to lock Recource1, but it's already locked). In one word, the regular deadlock situation.
But when I start it it doesn't lock itself and I'm getting this output:
C:\Users\ginz\C#\19-\Lab_01\Lab_01\bin\Debug>Lab_01.exe
Resource1 is used (0)
Resource2 is used (0)
Resource2 is free (0)
Resource1 is free (0)
Resource2 is used (1)
Resource1 is used (1)
Resource1 is free (1)
Resource2 is free (1)
So, the second thread is started only when the first thread has come to the end, but I think it should start much earlier. Why is this?
I know this behavior can be simply reproduced by using lock keyword, but in my case that's inappropriate way:
Object obj1 = new Object(), obj2 = new Object();
new Thread(new ThreadStart(delegate()
{
lock (obj1)
{
Thread.Sleep(1000);
lock (obj2)
{
Thread.Sleep(500);
}
}
})).Start();
new Thread(new ThreadStart(delegate()
{
lock (obj2)
{
Thread.Sleep(1000);
lock (obj1)
{
Thread.Sleep(500);
}
}
})).Start();
Could you please help me in this situation?
Thanks in advance,
Dmitry

Async Producer/Consumer

I have a instance of a class that is accessed from several threads. This class take this calls and add a tuple into a database. I need this to be done in a serial manner, as due to some db constraints, parallel threads could result in an inconsistent database.
As I am new to parallelism and concurrency in C#, I did this:
private BlockingCollection<Task> _tasks = new BlockingCollection<Task>();
public void AddDData(string info)
{
Task t = new Task(() => { InsertDataIntoBase(info); });
_tasks.Add(t);
}
private void InsertWorker()
{
Task.Factory.StartNew(() =>
{
while (!_tasks.IsCompleted)
{
Task t;
if (_tasks.TryTake(out t))
{
t.Start();
t.Wait();
}
}
});
}
The AddDData is the one who is called by multiple threads and InsertDataIntoBase is a very simple insert that should take few milliseconds.
The problem is that, for some reason that my lack of knowledge doesn't allow me to figure out, sometimes a task is been called twice! It always goes like this:
T1
T2
T3
T1 <- PK error.
T4
...
Did I understand .Take() completely wrong, am I missing something or my producer/ consumer implementation is really bad?
Best Regards,
Rafael
UPDATE:
As suggested, I made a quick sandbox test implementation with this architecture and as I was suspecting, it does not guarantee that a task will not be fired before the previous one finishes.
So the question remains: how to properly queue tasks and fire them sequentially?
UPDATE 2:
I simplified the code:
private BlockingCollection<Data> _tasks = new BlockingCollection<Data>();
public void AddDData(Data info)
{
_tasks.Add(info);
}
private void InsertWorker()
{
Task.Factory.StartNew(() =>
{
while (!_tasks.IsCompleted)
{
Data info;
if (_tasks.TryTake(out info))
{
InsertIntoDB(info);
}
}
});
}
Note that I got rid of Tasks as I'm relying on synced InsertIntoDB call (as it is inside a loop), but still no luck... The generation is fine and I'm absolutely sure that only unique instances are going to the queue. But no matter I try, sometimes the same object is used twice.
I think this should work:
private static BlockingCollection<string> _itemsToProcess = new BlockingCollection<string>();
static void Main(string[] args)
{
InsertWorker();
GenerateItems(10, 1000);
_itemsToProcess.CompleteAdding();
}
private static void InsertWorker()
{
Task.Factory.StartNew(() =>
{
while (!_itemsToProcess.IsCompleted)
{
string t;
if (_itemsToProcess.TryTake(out t))
{
// Do whatever needs doing here
// Order should be guaranteed since BlockingCollection
// uses a ConcurrentQueue as a backing store by default.
// http://msdn.microsoft.com/en-us/library/dd287184.aspx#remarksToggle
Console.WriteLine(t);
}
}
});
}
private static void GenerateItems(int count, int maxDelayInMs)
{
Random r = new Random();
string[] items = new string[count];
for (int i = 0; i < count; i++)
{
items[i] = i.ToString();
}
// Simulate many threads adding items to the collection
items
.AsParallel()
.WithDegreeOfParallelism(4)
.WithExecutionMode(ParallelExecutionMode.ForceParallelism)
.Select((x) =>
{
Thread.Sleep(r.Next(maxDelayInMs));
_itemsToProcess.Add(x);
return x;
}).ToList();
}
This does mean that the consumer is single threaded, but allows for multiple producer threads.
From your comment
"I simplified the code shown here, as the data is not a string"
I assume that info parameter passed into AddDData is a mutable reference type. Make sure that the caller is not using the same info instance for multple calls since that reference is captured in Task lambda .
Based on the trace that you provided the only logical possibility is that you have called InsertWorker twice (or more). There are thus two background threads waiting for items to appear in the collection and occasionally they both manage to grab an item and begin executing it.

Task Parallel Library Code Freezes in a Windows Forms Application - Works fine as a Windows Console Application

This question is a follow-up to a previous question that I had asked:
How to Perform Multiple "Pings" in Parallel using C#
I was able to get the accepted answer (a Windows console application) to work, but when I tried to run the code in a Windows forms application, the following code will freeze on the line containing Task.WaitAll(pingTasks.ToArray()). Here is the code that I am trying to run:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.NetworkInformation;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
List<String> addresses = new List<string>();
for (Int32 i = 0; i < 10; ++i) addresses.Add("microsoft.com");
List<Task<PingReply>> pingTasks = new List<Task<PingReply>>();
foreach (var address in addresses)
{
pingTasks.Add(PingAsync(address));
}
//Wait for all the tasks to complete
Task.WaitAll(pingTasks.ToArray());
//Now you can iterate over your list of pingTasks
foreach (var pingTask in pingTasks)
{
//pingTask.Result is whatever type T was declared in PingAsync
textBox1.Text += Convert.ToString(pingTask.Result.RoundtripTime) + Environment.NewLine;
}
}
private Task<PingReply> PingAsync(string address)
{
var tcs = new TaskCompletionSource<PingReply>();
Ping ping = new Ping();
ping.PingCompleted += (obj, sender) =>
{
tcs.SetResult(sender.Reply);
};
ping.SendAsync(address, new object());
return tcs.Task;
}
}
}
Does anyone have any ideas as to why it's freezing?
It's freezing because WaitAll waits on all of the tasks, and you're in the UI thread, so that's blocking the UI thread. Blocking the UI thread freezes your application.
What you want to do, since you're in C# 5.0, is await Task.WhenAll(...) instead. (You'll also need to mark that event handler as async in it's definition.) You won't need to change any other aspects of the code. That will work just fine.
await won't actually "wait" in the tasks. What it will do is, when it hits the await, it will wire up a continuation to the task you are awaiting on (in this case, the when all) and in that continuation it will run the remainder of the method. Then, after wiring up that continuation, it will end the method and return to the caller. This means that the UI thread isn't blocked, since this click event will end right away.
(Upon request) If you want to solve this using C# 4.0 then we'll need to start by writing WhenAll from scratch, since it was added in 5.0. Here is what I just whipped up. It's probably not quite as efficient as the library implementation, but it should work.
public static Task WhenAll(IEnumerable<Task> tasks)
{
var tcs = new TaskCompletionSource<object>();
List<Task> taskList = tasks.ToList();
int remainingTasks = taskList.Count;
foreach (Task t in taskList)
{
t.ContinueWith(_ =>
{
if (t.IsCanceled)
{
tcs.TrySetCanceled();
}
else if (t.IsFaulted)
{
tcs.TrySetException(t.Exception);
}
else //competed successfully
{
if (Interlocked.Decrement(ref remainingTasks) == 0)
tcs.TrySetResult(null);
}
});
}
return tcs.Task;
}
Here is another option based on this suggestion in the comments by svick.
public static Task WhenAll(IEnumerable<Task> tasks)
{
return Task.Factory.ContinueWhenAll(tasks.ToArray(), _ => { });
}
Now that we have WhenAll we just need to use that, as well as continuations, instead of await. Instead of WaitAll you'll use:
MyClass.WhenAll(pingTasks)
.ContinueWith(t =>
{
foreach (var pingTask in pingTasks)
{
//pingTask.Result is whatever type T was declared in PingAsync
textBox1.Text += Convert.ToString(pingTask.Result.RoundtripTime) + Environment.NewLine;
}
}, CancellationToken.None,
TaskContinuationOptions.None,
//this is so that it runs in the UI thread, which we need
TaskScheduler.FromCurrentSynchronizationContext());
Now you see why the 5.0 option is prettier, and this is a reasonably simple use case too.

Categories