How interrupt thread child in this case? I need interrupt foreach in thread child after throw exception in thread parent
Thread child;
Thread parent = new Thread(() =>
{
child = new Thread(() =>
{
for (int i = 0; i < int.MaxValue; i++)
{
Console.WriteLine("THREAD 1 = " + i);
}
});
child.Start();
try
{
child.Join();
}
catch (Exception ex)
{
System.Console.WriteLine(ex.ToString());
** // here????**
}
});
parent.Start();
parent.Interrupt();
Interrupt thread child
You cannot "interput" threads. Older .Net versions had Thread.Abort, but there are several good reasons why it should never be used.
What you should do is ask the thread to stop processing, and your thread should frequently check if needs to stop.
There are several ways to do this, one example would be the cancellation token. Let your thread take a cancellation token as input and in your loop add a call to
myCancellationToken.ThrowIfCancellationRequested();
Your caller would create a cancellation token source to generate the token and call .Cancel() to request the thread to abort.
However, using threads directly is very outdated, you should be using task based programming. There are common patterns to do most common tasks in a elegant and compact way, like DataFlow, Parallel.For, PLinq, concurrent collections etc.
Multi threaded programming is difficult. You need to have a fair bit of knowledge on the topic before you try to write anything intended for real world use. Thread safety bugs are quite easy to make, and are notoriously difficult to find and debug. So I would recommend studying thread safety, as well as modern threading patterns. This is not an area where trial and error is appropriate, since you are likely to create thing that work 99.9% of the time, or works 100% on your computer, but not in production.
JonasH's answer is a good one, but just for reference, here's how to use the CancellationToken with the original code:
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;
Thread parent = new Thread(() =>
{
Thread child = new Thread(() =>
{
for (int i = 0; i < int.MaxValue; i++)
{
if (ct.IsCancellationRequested)
{
break;
}
Console.WriteLine("THREAD 1 = " + i);
}
});
child.Start();
try
{
child.Join();
}
catch (Exception ex)
{
System.Console.WriteLine(ex.ToString());
cts.Cancel();
}
});
parent.Start();
parent.Interrupt();
Related
This question already has answers here:
How do I abort/cancel TPL Tasks?
(13 answers)
Closed 2 years ago.
The community reviewed whether to reopen this question 8 months ago and left it closed:
Original close reason(s) were not resolved
When using Parallel.ForEach(), is there a way to forcefully execute Thread.Abort on a specific thread?
I know that Thread.Abort() is not recommended.
I'm running a Parallel.ForEach() on a collection of a hundreds of thousands of entities.
The loop processes data going back 30 years in some cases. We've had a few issues where a thread hangs. While we are trying to get a grasp on that, was hoping to call implement a fail safe. If the thread runs for more than x amount of time, forcefully kill the thread.
I do not want to use a cancellation token.
It would be ugly, but haven't come to another solution. Would it be possible to:
Have each thread open a timer. Pass in reference of Thread.CurrentThread to timer
If the timer elapses, and processing hasn’t completed, call Thread.Abort on that timer
If needed, signal event wait handle to allow next patient to process
private void ProcessEntity(ProcessParams param,
ConcurrentDictionary<long, string> entities)
{
var options = new ParallelOptions
{
MaxDegreeOfParallelism = 2
};
Parallel.ForEach(person, options, p =>
{
ProcessPerson(param, p);
});
}
internal void ProcessPerson(ProcessParams param, KeyValuePair<long, string> p)
{
try
{
//...
}
catch (Exception ex)
{
}
param.eventWaitHandle?.WaitOne();
}
It seems that the Parallel.ForEach method is not resilient in the face of its worker threads being aborted, and behaves inconsistently. Other times propagates an AggregateException that contains the ThreadAbortException, and other times it throws an ThreadAbortException directly, with an ugly stack trace revealing its internals.
Below is a custom ForEachTimeoutAbort method that offers the basic functionality of the Parallel.ForEach, without advanced features like cancellation, loop state, custom partitioners etc. Its special feature is the TimeSpan timeout parameter, that aborts the worker thread of any item that takes too long to complete.
public static void ForEachTimeoutAbort<TSource>(
this IEnumerable<TSource> source,
Action<TSource> action,
int maxDegreeOfParallelism,
TimeSpan timeout)
{
// Arguments validation omitted
var semaphore = new SemaphoreSlim(maxDegreeOfParallelism, maxDegreeOfParallelism);
var exceptions = new ConcurrentQueue<Exception>();
try
{
foreach (var item in source)
{
semaphore.Wait();
if (!exceptions.IsEmpty) { semaphore.Release(); break; }
ThreadPool.QueueUserWorkItem(_ =>
{
var timer = new Timer(state => ((Thread)state).Abort(),
Thread.CurrentThread, Timeout.Infinite, Timeout.Infinite);
try
{
timer.Change(timeout, Timeout.InfiniteTimeSpan);
action(item);
}
catch (Exception ex) { exceptions.Enqueue(ex); }
finally
{
using (var waitHandle = new ManualResetEvent(false))
{
timer.Dispose(waitHandle);
// Wait the timer's callback (if it's queued) to complete.
waitHandle.WaitOne();
}
semaphore.Release();
}
});
}
}
catch (Exception ex) { exceptions.Enqueue(ex); }
// Wait for all pending operations to complete
for (int i = 0; i < maxDegreeOfParallelism; i++) semaphore.Wait();
if (!exceptions.IsEmpty) throw new AggregateException(exceptions);
}
A peculiarity of the ThreadAbortException is that it cannot be caught. So in order to prevent the premature completion of the parallel loop, the Thread.ResetAbort method must be called from the catch block.
Usage example:
ForEachTimeoutAbort(persons, p =>
{
try
{
ProcessPerson(param, p);
}
catch (ThreadAbortException)
{
Thread.ResetAbort();
}
}, maxDegreeOfParallelism: 2, timeout: TimeSpan.FromSeconds(30));
The .NET Framework is the only platform where the ForEachTimeoutAbort method could be used. For .NET Core and .NET 5 one could try converting it to ForEachTimeoutInterrupt, and replace the call to Abort with a call to Interrupt. Interrupting a thread is not as effective as aborting it, because it only has effect when the thread is in a waiting/sleeping mode. But it may be sufficient in some scenarios.
I am currently working on a piece of software that uses an assembly from a different department.I call a Method from this assembly like this:
using (var connection = (IConnection) Factory.GetObject(typeof (IConnection)))
The code used to work perfectly fine. But for the last few minutes it seemed like my program was doing nothing when I tried to launch it. Pressing pause while debugging showed me it got "stuck" at the line above.My guess is they're just doing some maintenance or something but that's not the point here.
So I though it would be nice to tell the user what went wrong if the program doesn't start. Something simple like
MessageBox.Show("Could not connect", "Connection Error");
And then close the program. My question is:
How do I terminate the execution of a command after a set amount of time and jump somewhere else?My guess would be moving it to a separate thread and then putting the calling thread to sleep for a few seconds after which it disposes of the extra thread if it isn't completed yet. But that seems really dirty to me and there's got to be a better way.
Your question can be separated into two parts:
How to terminate the execution of a command?
The only way is to abort the thread. But don't do it. There is no guaranteed and safe way. There are such methods like Thread.Interrupt and Thread.Abort that can wake up the thread. But they will work only if the thread is in the WaitSleepJoin state and it hangs in managed code.
Seems like you already know it. But once again, if something inside the assembly hangs infinitely the execution of code then the thread is probably "gone". So you are right that the program should be closed.
... jump somewhere else?
Good approach is using of TPL and async model.
Here is an extension method to wrap up any Task and expires after timeout.
public static async Task TimeoutAfter(this Task task, int millisecondsTimeout)
{
if (task == await Task.WhenAny(task, Task.Delay(millisecondsTimeout)))
await task;
else
throw new TimeoutException();
}
Then use it
try
{
using (var result = await Task.Run(() => (IConnection)Factory.GetObject(typeof(IConnection))).TimeoutAfter(1000))
{
...
}
}
catch (TimeoutException ex)
{
//timeout
}
Here you can find more information
A simple way of doing it without extra libraries or extension methods:
using ( var task = new Task<IConnection>( () => Factory.GetObject( typeof( IConnection ) ) ) )
{
task.Start();
if( !task.Wait( timeoutMilliseconds ) )
{
throw new TimeoutException();
}
IConnection result = task.Result;
}
Task.Wait does what you want, because you can throw an exception if it returns false (task didn't complete in time.)
It's even simpler if you have an Action that doesn't return something:
if ( !Task.Run( action ).Wait( timeoutMilliseconds ) )
{
throw new TimeoutException();
}
Where action is some Action or lambda.
The easiest way to do this, if a native timeout is not implemented, as you mentioned, is a separate thread to load it on. Although this sounds like it'll be really dirty, it's as simple as (using Rx):
Task<IConnection> connectionTask = Observable.Start(() => Factory.GetObject(typeof (IConnection)), Scheduler.Default).Timeout(TimeSpan.FromSeconds(20)).ToTask());
using (var connection = connectionTask.Result)
{
...
}
You can tweak the Scheduler if you don't want it to run on the threadpool. It will throw a TimeoutException if the Factory.GetObject call takes longer than 20 seconds.
You could use CancellationTokenSource to set a timeout on the operation
var timeoutCts = new CancellationTokenSource();
try
{
timeoutCts.CancelAfter(300000); // Cancel after 5 minutes
// ... run your long term operation
}
catch (OperationCanceledException ex)
{
// Handle the timeout
}
Please see this documentation from Microsoft
using System;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
Task t = Task.Run(() =>
{
Random rnd = new Random();
long sum = 0;
int n = 5000000;
for (int ctr = 1; ctr <= n; ctr++)
{
int number = rnd.Next(0, 101);
sum += number;
}
Console.WriteLine("Total: {0:N0}", sum);
Console.WriteLine("Mean: {0:N2}", sum / n);
Console.WriteLine("N: {0:N0}", n);
});
TimeSpan ts = TimeSpan.FromMilliseconds(150);
if (!t.Wait(ts))
Console.WriteLine("The timeout interval elapsed.");
}
}
I was testing how many threads my computer can handle before something goes wrong, using the following code:
static void Main(string[] args)
{
List<Thread> threads = new List<Thread>();
int count = 0;
try
{
while (true)
{
Console.Write('m'); // make
Thread thread = new Thread(() => { Thread.Sleep(Timeout.Infinite); }, 1024 * 64);
Console.Write('s'); // start
thread.Start();
Console.Write('p'); // suspend
thread.Suspend();
Console.Write('a'); // add
threads.Add(thread);
Console.Write(' ');
Console.WriteLine(count++);
}
}
catch (Exception e)
{
Console.WriteLine("\nGot exception of type " + e.GetType().Name);
}
Console.WriteLine(count);
Console.ReadKey(true);
}
I was expected the new Thread(...) constructor to throw an exception (maybe OutOfMemoryException) when the system could not make any more threads, but instead the constructor hangs and never returns.
Instead of the output from the above being
...
mspa 67
m
Got exception of type OutOfMemoryException
it is rather
...
mspa 67
m <- it hangs while 'm'aking the thread
So, the TLDR: why does new Thread(...) hang instead of throw an exception when there are too many threads?
thread.Suspend();
That's an evil, evil, evil method. Strongly deprecated in .NET version 2.0, it isn't very clear how you got past the [Obsolete] message and not notice this. I'll quote the MSDN note about this method:
Do not use the Suspend and Resume methods to synchronize the activities of threads. You have no way of knowing what code a thread is executing when you suspend it. If you suspend a thread while it holds locks during a security permission evaluation, other threads in the AppDomain might be blocked. If you suspend a thread while it is executing a class constructor, other threads in the AppDomain that attempt to use that class are blocked. Deadlocks can occur very easily.
Yup, that's what a deadlock looks like.
I have 30+ tasks that can be executed in parallel.
I use ThreadPool for each task.
But parent-function should not return until all tasks has completed.
I need a thread sync handle that would release WaitOne when its count reaches 0.
Something like:
foo.StartWith(myTasks.Count);
foreach (var task in myTasks) {
ThreadPool.QueueUserWorkItem(state => { task(state); foo.Release(); });
}
foo.WaitOne();
Semaphore feels right, just can't figure out how to apply it here.
int running = myTasks.Count;
AutoResetEvent done = new AutoResetEvent(false);
foreach (var task in myTasks) {
ThreadPool.QueueUserWorkItem(state => {
task(state);
if (0 == Interlocked.Decrement(ref running))
done.Set ();
});
}
done.WaitOne();
With C# 4.0 you can use the new CountdownEvent primitive.
Joe Duffy wrote a great article on this sort of thing:
CLR Inside Out: 9 Reusable Parallel Data Structures and Algorithms
I'm eyballing the CountdownLatch as particularly appropriate for your requirements.
According to this article: Overview of Synchronization Primitives
C# has a built-in type for this scenario, CountDownEvent: CountdownEvent Class
Or a similiar one: Barrier (.NET Framework)
For newer versions, use the TPL (Task Parallel Library) , and for this scenerio this code is relevant:
// Create an ActionBlock<int> object that prints its input
// and throws ArgumentOutOfRangeException if the input
// is less than zero.
var throwIfNegative = new ActionBlock<int>(n =>
{
Console.WriteLine("n = {0}", n);
if (n < 0)
{
throw new ArgumentOutOfRangeException();
}
});
// Post values to the block.
throwIfNegative.Post(0);
throwIfNegative.Post(-1);
throwIfNegative.Post(1);
throwIfNegative.Post(-2);
throwIfNegative.Complete();
// Wait for completion in a try/catch block.
try
{
throwIfNegative.Completion.Wait();
}
catch (AggregateException ae)
{
// If an unhandled exception occurs during dataflow processing, all
// exceptions are propagated through an AggregateException object.
ae.Handle(e =>
{
Console.WriteLine("Encountered {0}: {1}",
e.GetType().Name, e.Message);
return true;
});
}
/* Output:
n = 0
n = -1
Encountered ArgumentOutOfRangeException: Specified argument was out of the range
of valid values.
*/
from https://msdn.microsoft.com/en-us/library/hh228603.aspx
In .net 3.5
trying to ThreadPool.QueueUserWorkItem(a=> {Work()}); when the ThreadPool has no available threads caused BeginInvoke lock up.
void Work()
{
Action executor = () = { DoSomething(); };
IAsyncResult result = executor.BeginInvoke(null, null);
using (WaitHandle hWait = result.AsyncWaitHandle)
{
if (hWait.WaitOne(timeoutMilliseconds))
{
executor.EndInvoke(result);
}
else
{ throw new ImDyingException(); }
}
}
How can I make the BeginInvoke use a non-pooled thread?
You can't. It sounds like you are vastly over-using the pool. Perhaps consider a throttled queue / custom thread pool (i.e. a synchronized producer/consumer queue)?
(don't increase the pool size; that is almost always the wrong approach to take)