C# / .Net Multithreading Interview Questions

;
Filters
Tag Filters
Level
votes
0
answers
0
Order Nuvigil 150 MG 100 pills online
Oliver Jackson 11/11/2020 12:09 PM
Advanced
multithreading
No answers yet.
votes
2
answers
1
Answer

Interlocked class provides a set of static functions which allow a few simple operations to be performed thread safe. Apart from convenience, these functions are much faster than having a lock around an equivalent statement (explained below). First, following is a list of Interlocked functions with explanation in comments.

long counter = 0;
            
//Increment counter by 1
Interlocked.Increment (ref counter);                              
 
//Decrement counter by 1
Interlocked.Decrement (ref counter);                              
 
//Add 10 to counter
Interlocked.Add (ref counter, 10);                                 
 
//Set counter = 100 and return the original value of counter before it was changed.
//This usually does not require a lock but consider a scenario where
//counter is a 64 bit value and code running on a 32 bit machine.
//In such a scenario the assignment happens in 2 steps for each 32 bit part
//and hence the assignment is not atomic.
var oldCounterValue = Interlocked.Exchange (ref counter, 100);

// Read a 64-bit value atomically into another variable (val)
var val = Interlocked.Read(ref counter);               
 
// Set counter = 999 if counter == 1000
Interlocked.CompareExchange(ref counter, 999, 1000);  

As I mentioned these statements are faster in most cases and especially on modern CPUs, as these functions execute in a lock free manner or as a single instruction wherever possible, thus avoiding the need for a lock (they do use memory barriers though, to avoid reordering issues etc.) For example CompareExchange function uses the cpu instruction CMPXCHG which allows Comparison and Exchange of values in a single instruction which cannot be pre-empted.

votes
2
answers
1
What is Thread Affinity? How do we get around the problem of thread affinity in desktop applications?
Super Human 11/20/2014 5:17 PM
Beginner
c#
.net
wpf
winforms
multithreading
Answer

In Desktop Applications (WPF or Winforms), any UI element created on a thread is accessible only to that thread, and is not available to other threads. This is called Thread Affinity. If an attempt is made to access the ui element from any thread, other than a thread that created it, it can leave the state of the control in an invalid state or the runtime will throw an exception. In WPF all objects which subsequently derive from DispatcherObject have threads affinity (Yes, that includes some non UI objects like ObservableCollection too). In winforms objects deriving from Control class have thread affinity. So what if some thread wants to access a UI element not created by it? As it cannot run the code which accesses the UI element, it has to marshall the code to its owner, so that the owner thread can run the code. We have a few options to simplify this task:


Using Dispatcher.Invoke / BeginInvoke (WPF) 

Action uiAction = () => txtbox.Text = "Done"; // The code we want to pass to UI thread
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, uiAction);


Using Control.Invoke / BeginInvoke (Winforms)

Action uiAction = () => txtbox.Text = "Done";
txtbox.Invoke(uiAction);


Using BackgroundWorker 

Instead of manually assigning work to another thread from UI thread, you can use BackgroundWorker class. 

var bgWorker = new BackgroundWorker { WorkerReportsProgress = true };

bgWorker.DoWork += (o, e) =>
{
    //Worker thread code. Gets called in a Non-UI thread.
};

bgWorker.ProgressChanged += (o, e) =>
{
    //Progress change gets called on the UI thread. Controls can be accessed safely
};
            
bgWorker.RunWorkerCompleted += (o, e) =>
{
    //gets called when worker thread finishes. UI thread. Controls can be accessed safely
};

bgWorker.RunWorkerAsync();


Using Task Continuations 

If we use the TaskScheduler returned from helper function TaskScheduler.FromCurrentSynchronizationContext() in the continuation task, the code will get executed in a UI thread.

Task.Factory.StartNew<string>(CodeToRunOnNonUIThread)
    .ContinueWith(ant => txtBox.Text = "Done",
    TaskScheduler.FromCurrentSynchronizationContext());
votes
0
answers
1
What is a CountdownEvent
Charlie 11/9/2014 5:17 PM
Beginner
multithreading
.net
.net-4.0
Answer

CountdownEvent is a synchronization primitive that unblocks its waiting threads after it has been signaled a certain number of times. E.g. if we create a CountdownEvent with a parameter of 3, threads waiting on it will remain blocked until a Signal event is called 3 times.


static CountdownEvent countdownEvent= new CountdownEvent (3);
static void Main()
{
  new Thread (Func).Start (1);
  new Thread (Func).Start (2);
  new Thread (Func).Start (3);
 
  countdownEvent.Wait();   // The thread will block until we receieve three Signals.
  Console.WriteLine("Three Signals received. Now I can proceed");
}
 
static void Func (object id)
{
  Thread.Sleep((int)id * 1000);
  Console.WriteLine("Signalling");
  countdownEvent.Signal();
}

Notes:

CountdownEvent is available only in .net framework 4.0 and above
It is purely managed. So cannot be used for interprocess signalling.
CountdownEvent’s count can be increased by calling the AddCount function (beware if it has already reached zero, AddCount will throw an exception)
Calling Reset() will reset its count to the original value and will unsignal the construct.

votes
1
answers
1
What is a ManualResetEvent and a AutoResetEvent
K Bonneau 11/8/2014 8:10 PM
Beginner
multithreading
.net
Answer

ManualResetEvent and AutoResetEvents are signalling constructs. We'd use these constructs if we want threads to wait until signalled.

ManualResetEvent is like a door. If the door is closed all threads would wait at the door. Some other thread can signal for the door to open. Once opened all threads can pass through the "door" and continue execution. The door can be closed again.

Creating the ManualResetEvent object. (the "door")

ManualResetEvent mre = new ManualResetEvent(false);

false = door is closed by default, true = door is open by default.

Wait for the door to open:

mre.WaitOne();

Opening the door:

mre.Set();

Closing the door:

mre.Reset();

AutoResetEvent is similar to ManualResetEvent except that it behaves as a ticket turnstile instead of a door i.e. when signalled only one thread is allowed to proceed and the gate is automatically closed. Other threads then have to wait for more signals.

Creating a AutoResetEvent.

AutoResetEvent are = new AutoResetEvent(false);

false = turnstile is created as closed , true = turnstile is created as open.

Other methods are similar to ManualResetEvent.

Note that if no thread is waiting and a Set is called, the signal is not lost. The "turnstile" remains open until some thread calls WaitOne and is allowed to enter.

Next Page > < Previous Page