TaskScheduler to always run on the same thread - c#

I have some code using a ReaderWriterLockSlim. I acquire a write lock on it when a certain object is constructed, and release it when that object is disposed some time later. However, because of where those calls are coming from, I can't guarantee that they'll be on the same thread, which is a requirement of the ReaderWriterLockSlim.
I believe a reasonable solution would be to run the construction and disposal of the object on a dedicated thread, and have the calling code wait for that task to complete (but keep the thread alive). It seems messy, but I can't think of another approach without massively restructuring our code.
Is there an existing TaskScheduler subclass that will allow me to run two tasks on the same thread?
I am of course open to another paradigm of doing this.

I had a similar problem, so I hope that my solution is going to help you too.
Basically, the problem is that ReaderWriterLockSlim has thread affinity, meaning that thread that acquired a lock is the only one that can release it.
Solution to this is to create one more dedicated thread, but opposed to what you suggested, this thread is going to be dedicated to acquiring and releasing a lock.
I guess that your code looks something like this:
public class ClassUsingReaderWriterLockSlim
{
private ReaderWriterLockSlim rwsLock;
public void MethodThatAcquiresLock()
{
rwsLock.EnterWriteLock();
}
public void MethodThatReleasesLock()
{
rwsLock.ExitWriteLock();
}
}
And a code that solves your problem will look like this:
public class ClassUsingReaderWriterLockSlim
{
private ReaderWriterLockSlim rwsLock;
Thread dedicatedThreadForReaderWriterLockSlim;
Queue<string> commandsForDedicatedThread;
public ClassUsingReaderWriterLockSlim()
{
commandsForDedicatedThread = new Queue<string>();
dedicatedThreadForReaderWriterLockSlim = new Thread(ThreadFunction);
dedicatedThreadForReaderWriterLockSlim.Start();
}
private void ThreadFunction(object obj)
{
while (!terminatingCondition)
{
// Wait until something is in queue...
if (commandsForDedicatedThread.Count > 0)
{
switch (commandsForDedicatedThread.Dequeue())
{
case "ENTER LOCK":
rwsLock.EnterWriteLock();
case "EXIT LOCK":
rwsLock.EnterWriteLock();
default:
// Do nothing...
}
}
}
}
public void MethodThatAcquiresLock()
{
commandsForDedicatedThread.Enqueue("ENTER LOCK");
}
public void MethodThatReleasesLock()
{
commandsForDedicatedThread.Enqueue("EXIT LOCK");
}
}
Well, for you production code you would make this a little differently but the basic idea is to have dedicated thread that is going to do locking and unlocking, and in this way it won't be important from which thread call comes to the methods that are supposed to lock and unlock code/resources...
Hope this helps you.

Related

Deadlock in WPF from main thread and worker thread

I have a code like this:
private static var Locker = new Object();
private void SensitiveCode()
{
lock (Locker)
{
SomeCodeSensitive(); .....
Dispatcher.BeginInvoke(new Action(() =>
{
SomeCodeThatUpdatesUI();
}));
MoreCodeSensitive();
}
}
Also i have a thread running doing something like this:
while (X)
{
SensitiveCode();
Thread.Sleep(5000);
}
Now in my main thread I sometimes call SensitiveCode(); SensitiveCode() is on lock because it must not be called from 2 threads at same time.
Well, the problem is I don't know why, sometimes i find a deadlock, sometimes on UI (the UI freezes), sometimes on thread. I don't know what is happening, one of the threads stops in lock() cause it is supposed that variable "Locker" is in use for the other thread, but that is not true. I think that the problem could be the BeginInvoke inside the lock, but I think that should not be enough to lock this code.
Also, it is very hard to reproduce the problem, I've been testing for 3 hours and it has appeared only 2 times.
Does someone know what could it be?
Thanks!
Update Due to questions:
SensitiveCode() is doing work with some AsyncObservableCollection objects (class from http://www.thomaslevesque.com/2009/04/17/wpf-binding-to-an-asynchronous-collection/) .
Doing things like reading from database and filling those AsyncObservableCollection(). I lock this action because I cannot allow the thread updates my AsyncObservableCollection while the user does it at the same time.
Also, the UI does this
Dispatcher.BeginInvoke(new Action(() =>
{
if (tables.Count != TablesInWindow.Count)
TablesInWindow.ClearAndAddRange(tables);
else
{
if (tables.Where((t, i) => !TablesInWindow[i].Equals(t)).Any())
TablesInWindow.ClearAndAddRange(tables);
}
ButtonPageBack.IsEnabled = canGoBack;
ButtonPageNext.IsEnabled = canGoFoward;
}));
Update 2:
After doing again, here is a screenshot of the threads when the deadlock ocurred
http://i.imgur.com/8xyIy6h.png
MovePageForward is the action I do on the UI, it contains this code:
public static void MakePageForward()
{
lock (ConfigParameters.Lock)
{
_currentPage++;
ShowTablesInWindow();
}
}
TimerConnectionTick has the following code:
private static void TimerConnectionTick()
{
while (!_thisDisposing)
{
ShowTablesInWindow();
if (!_thisDisposing)
Thread.Sleep(5000);
}
}
Without seeing all of your code, it is hard to debug. Is it possible that somewhere within your SomeCodeThatUpdatesUI() method you are also triggering a lock on Locker? If you are triggering a lock recursively it will pass through without issue, however if you are doing so within your BeginInvoke on the Dispatcher thread (which may be different than your current thread as you mentioned you call this from different threads), it will lock and cause a Deadlock.
If that is the case, perhaps you can either refactor when you need to lock, or use something like a ReaderWriterLockSlim (https://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim(v=vs.110).aspx)

How to create multiple threads from an application and do not listen to their response?

I am trying to do the following :
I have a server that is supposed to get many messages from a queue and process them. Now what I want is to create a new thread for every message and those threads will handle the response to the queue, I just want my server (core thread) to be just listening to messages and creating threads, not caring of what happens to them.
How can I achieve this? I know I can use the Thread class to create a thread but then the application just keeps listening to the thread until if finishes.
Also I can create an async method and run it but what happens when it finishes? Also the method is supposed to be static if I want it to be async but in my current application that is not a solution since I use many non static variables into this method.
Any ideas would be appreciated.
Unless you have very specific reason, I'd recommend using Tasks instead of Threads.
Likely they'll run in background anyway, but they produce less CPU/memory overhead and (in my opinion) are easier to handle in case of exception,...
Task t = Task.Run(() => ProcessMessage(message));
Maybe take a look at this introduction
What do you mean with
I know I can use the Thread class to create a thread but then the application just keeps listening to the thread until if finishes.
Just spawn the thread and let it run:
{
Thread t = new Thread(Foo);
t.Start();
}
public void Foo()
{ }
This won't make the main thread listen to the child thread, it just spawn them and continue working on following instructions.
BTW there are tons of result on how to create and run threads.
Since I don't like when others do it, here are simple examples of each way (asynchrnous/task-based), and you pick which one you like.
Asynchronous Implementation
int main()
{
while(true)
{
string data = SomeMethodThatReturnsTheNextDataFromQueue();
ProcessDataAsync(data);
}
}
async private void ProcessDataAsync(string msg)
{
// The *await* keyword returns to caller and allows main thread to continue looping.
bool result = await ParseDataAndSaveSomewhere(msg);
return;
}
Task-Based Implementation
int main()
{
while(true)
{
string data = SomeMethodThatReturnsTheNextDataFromQueue();
Task task = new Task(() => { ProcessData(data) });
task.Start();
}
}
private void ProcessData(string data)
{
// Do work
}

Asynchronous/Synchronous concurrent calls with queuing

I have a scenario where I'm doing some Actor-Model kind of messagequeing where I want a method to insert a Task or delegate into a queue (possibly the new ConcurrentQueue) , wait for some other process to process the queue, execute the task and then return the result, preferably without locking. The method might be called both synchronously and asynchronously. Only one queued action might run simultaneously
I can't wrap my head around how to accomplish this in a somewhat performant manner, please help :)
EDIT
Here's an attempt, anyone seeing any problems with this approach (exception handling excluded) ? Also, I can imagine this has quite a lot of overhead compared to simply locking, and how does it compare to for instance using asynchronous delegates?
public partial class Form1 : Form
{
private BlockingCollection<Task<int>> blockingCollection = new BlockingCollection<Task<int>>(new ConcurrentQueue<Task<int>>());
private int i = 0;
public Form1() {
InitializeComponent();
Task.Factory.StartNew(() =>
{
foreach (var task in blockingCollection.GetConsumingEnumerable()) {
task.Start();
task.Wait();
}
});
}
public int Queue() {
var task = new Task<int>(new Func<int>(DoSomething));
this.blockingCollection.Add(task);
task.Wait();
return task.Result;
}
public int DoSomething() {
return Interlocked.Increment(ref this.i);
}
private void button1_Click(object sender, EventArgs e) {
Task.Factory.StartNew(() => Console.Write(this.Queue()));
}
}
The TPL should do that for you - just call Wait() on your Task<T> - however, there is no way to do this without blocking; by definition, in your scenario that is exactly want you want to do. Blocking might be implemented via a lock, but there are other ways too - the TPL hides this. Personally, in a similar scenario I do it with a custom queue and a mini-pool of objects I can use to lock against (never exposed outside the wrapper).
You might also want to look at the C# 5 async/await stuff.
But note: if you aren't going to do anything useful while you are waiting, you might as well run that code directly on the current thread - unless the issue is thread-bound, for example a multiplexer. If you are interested, later today (or over the weekend) I intend releasing the multiplexer that stackoverflow uses to talk to redis, which (in synchronous mode, at least) has exactly the problems you describe.
As a side note; if you can work with a callback (from the other thread), and not have to wait on completion, that can be more efficient overall. But it doesn't fit every scenario.

How to async add elements to Queue<T> in C#?

public void EnqueueTask(int[] task)
{
lock (_locker)
{
_taskQ.Enqueue(task);
Monitor.PulseAll(_locker);
}
}
So, here I'm adding elements to my queue and than threads do some work with them.How can I add items to my queue asynchronously?
If you using .net V4 have a look at the new thread safe collections, they are mostly none blocking so will properly avoid the need for an async add.
Since your using Queue<T> (recommended), Queue.Synchronized can't be used.
But besides that I would use the thread pool. But your EnqueueTask method kind of implies that the threading logic is handled outside of your "TaskQueue" class (your method implies that it is a Queue of tasks).
Your implementation also implies that it is not "Here" we wan't to add logic but rather in another place, the code you have there isn't really blocking for long so I would turn things upside down.
It also implies that the thing taking things off the queue is already on another thread since you use "PulseAll" to weak that thread up.
E.g.
public void StartQueueHandler()
{
new Thread(()=>StartWorker).Start();
}
private int[] Dequeue()
{
lock(_locker)
{
while(_taskQ.Count == 0) Monitor.Wait(_locker);
return _taskQ.Dequeue();
}
}
private void StartWorker(object obj)
{
while(_keepProcessing)
{
//Handle thread abort or have another "shot down" mechanism.
int[] work = Dequeue();
//If work should be done in parallel without results.
ThreadPool.QueueUserWorkItem(obj => DoWork(work));
//If work should be done sequential according to the queue.
DoWork(work);
}
}
Maybe something like this could work:
void AddToQueue(Queue queue, string mess) {
var t = new Thread(() => Queue.Synchronized(queue).Enqueue(mess));
t.Start();
}
The new thread ensures that your current thread does not block.
Queue.Syncronized handles all locking of the queue.
It could be replaced with your locker code, might be better performance.
The code from your question seems to indicate that you are attempting to implement a blocking queue. I make that obseration from the call to Monitor.PulseAll after the Queue<T>.Enqueue. This is the normal pattern for signalling the dequeuing thread. So if that is the case then the best option is to use the BlockingCollection class which is available in .NET 4.0.

Is there a way to indefinitely pause a thread?

I've been working on a web crawling .NET app in my free time, and one of the features of this app that I wanted to included was a pause button to pause a specific thread.
I'm relatively new to multi-threading and I haven't been able to figure out a way to pause a thread indefinitely that is currently supported. I can't remember the exact class/method, but I know there is a way to do this but it has been flagged as obsolete by the .NET framework.
Is there any good general purpose way to indefinitely pause a worker thread in C# .NET.
I haven't had a lot of time lately to work on this app and the last time I touched it was in the .NET 2.0 framework. I'm open to any new features (if any) that exist in the .NET 3.5 framework, but I'd like to know of solution that also works in the 2.0 framework since that's what I use at work and it would be good to know just in case.
Never, ever use Thread.Suspend. The major problem with it is that 99% of the time you can't know what that thread is doing when you suspend it. If that thread holds a lock, you make it easier to get into a deadlock situation, etc. Keep in mind that code you are calling may be acquiring/releasing locks behind the scenes. Win32 has a similar API: SuspendThread and ResumeThread. The following docs for SuspendThread give a nice summary of the dangers of the API:
http://msdn.microsoft.com/en-us/library/ms686345(VS.85).aspx
This function is primarily designed for use by debuggers. It is not intended to be used for thread synchronization. Calling SuspendThread on a thread that owns a synchronization object, such as a mutex or critical section, can lead to a deadlock if the calling thread tries to obtain a synchronization object owned by a suspended thread. To avoid this situation, a thread within an application that is not a debugger should signal the other thread to suspend itself. The target thread must be designed to watch for this signal and respond appropriately.
The proper way to suspend a thread indefinitely is to use a ManualResetEvent. The thread is most likely looping, performing some work. The easiest way to suspend the thread is to have the thread "check" the event each iteration, like so:
while (true)
{
_suspendEvent.WaitOne(Timeout.Infinite);
// Do some work...
}
You specify an infinite timeout so when the event is not signaled, the thread will block indefinitely, until the event is signaled at which point the thread will resume where it left off.
You would create the event like so:
ManualResetEvent _suspendEvent = new ManualResetEvent(true);
The true parameter tells the event to start out in the signaled state.
When you want to pause the thread, you do the following:
_suspendEvent.Reset();
And to resume the thread:
_suspendEvent.Set();
You can use a similar mechanism to signal the thread to exit and wait on both events, detecting which event was signaled.
Just for fun I'll provide a complete example:
public class Worker
{
ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
ManualResetEvent _pauseEvent = new ManualResetEvent(true);
Thread _thread;
public Worker() { }
public void Start()
{
_thread = new Thread(DoWork);
_thread.Start();
}
public void Pause()
{
_pauseEvent.Reset();
}
public void Resume()
{
_pauseEvent.Set();
}
public void Stop()
{
// Signal the shutdown event
_shutdownEvent.Set();
// Make sure to resume any paused threads
_pauseEvent.Set();
// Wait for the thread to exit
_thread.Join();
}
public void DoWork()
{
while (true)
{
_pauseEvent.WaitOne(Timeout.Infinite);
if (_shutdownEvent.WaitOne(0))
break;
// Do the work here..
}
}
}
The Threading in C# ebook summarises Thread.Suspend and Thread.Resume thusly:
The deprecated Suspend and Resume methods have two modes – dangerous and useless!
The book recommends using a synchronization construct such as an AutoResetEvent or Monitor.Wait to perform thread suspending and resuming.
If there are no synchronization requirements:
Thread.Sleep(Timeout.Infinite);
I just implemented a LoopingThread class which loops an action passed to the constructor. It is based on Brannon's post. I've put some other stuff into that like WaitForPause(), WaitForStop(), and a TimeBetween property, that indicates the time that should be waited before next looping.
I also decided to change the while-loop to an do-while-loop. This will give us a deterministic behavior for a successive Start() and Pause(). With deterministic I mean, that the action is executed at least once after a Start() command. In Brannon's implementation this might not be the case.
I omitted some things for the root of the matter. Things like "check if the thread was already started", or the IDisposable pattern.
public class LoopingThread
{
private readonly Action _loopedAction;
private readonly AutoResetEvent _pauseEvent;
private readonly AutoResetEvent _resumeEvent;
private readonly AutoResetEvent _stopEvent;
private readonly AutoResetEvent _waitEvent;
private readonly Thread _thread;
public LoopingThread (Action loopedAction)
{
_loopedAction = loopedAction;
_thread = new Thread (Loop);
_pauseEvent = new AutoResetEvent (false);
_resumeEvent = new AutoResetEvent (false);
_stopEvent = new AutoResetEvent (false);
_waitEvent = new AutoResetEvent (false);
}
public void Start ()
{
_thread.Start();
}
public void Pause (int timeout = 0)
{
_pauseEvent.Set();
_waitEvent.WaitOne (timeout);
}
public void Resume ()
{
_resumeEvent.Set ();
}
public void Stop (int timeout = 0)
{
_stopEvent.Set();
_resumeEvent.Set();
_thread.Join (timeout);
}
public void WaitForPause ()
{
Pause (Timeout.Infinite);
}
public void WaitForStop ()
{
Stop (Timeout.Infinite);
}
public int PauseBetween { get; set; }
private void Loop ()
{
do
{
_loopedAction ();
if (_pauseEvent.WaitOne (PauseBetween))
{
_waitEvent.Set ();
_resumeEvent.WaitOne (Timeout.Infinite);
}
} while (!_stopEvent.WaitOne (0));
}
}
Beside suggestions above, I'd like to add one tip. In some cases, use BackgroundWorker can simplify your code (especially when you use anonymous method to define DoWork and other events of it).
In line with what the others said - don't do it. What you really want to do is to "pause work", and let your threads roam free. Can you give us some more details about the thread(s) you want to suspend? If you didn't start the thread, you definitely shouldn't even consider suspending it - its not yours. If it is your thread, then I suggest instead of suspending it, you just have it sit, waiting for more work to do. Brannon has some excellent suggestions for this option in his response. Alternatively, just let it end; and spin up a new one when you need it.
The Suspend() and Resume() may be depricated, however they are in no way useless.
If, for example, you have a thread doing a lengthy work altering data, and the user wishes to stop it, he clicks on a button. Of course, you need to ask for verification, but, at the same time you do not want that thread to continue altering data, if the user decides that he really wants to abort.
Suspending the Thread while waiting for the user to click that Yes or No button at the confirmation dialog is the only way to prevent it from altering the data, before you signal the designated abort event that will allow it to stop.
Events may be nice for simple threads having one loop, but complicated threads with complex processing is another issue.
Certainly, Suspend() must never be used for syncronising, since its usefulness is not for this function.
Just my opinion.

Categories