Catch a Thread's Exception in the Caller Thread

Catch a thread's exception in the caller thread?

The problem is that thread_obj.start() returns immediately. The child thread that you spawned executes in its own context, with its own stack. Any exception that occurs there is in the context of the child thread, and it is in its own stack. One way I can think of right now to communicate this information to the parent thread is by using some sort of message passing, so you might look into that.

Try this on for size:

import sys
import threading
import queue

class ExcThread(threading.Thread):

def __init__(self, bucket):
threading.Thread.__init__(self)
self.bucket = bucket

def run(self):
try:
raise Exception('An error occured here.')
except Exception:
self.bucket.put(sys.exc_info())

def main():
bucket = queue.Queue()
thread_obj = ExcThread(bucket)
thread_obj.start()

while True:
try:
exc = bucket.get(block=False)
except queue.Empty:
pass
else:
exc_type, exc_obj, exc_trace = exc
# deal with the exception
print exc_type, exc_obj
print exc_trace

thread_obj.join(0.1)
if thread_obj.isAlive():
continue
else:
break

if __name__ == '__main__':
main()

How to catch an exception which occured in a thread?

The exact answer to my problem was given in an answer to another question (I marked mine as duplicate, but it is really that particular answer which is perfect in my context).

The code in my question modified to account for the solution:

import concurrent.futures

class Checks:

@staticmethod
def isok():
print("OK")

@staticmethod
def isko():
raise Exception("KO")

# db will keep a map of method namles in Check with the actual (executable) method
db = {}

with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
for check in [k for k in dir(Checks) if not k.startswith('_')]:
db[check] = executor.submit(getattr(Checks, check))
for future in concurrent.futures.as_completed([db[k] for k in db.keys()]):
if future.exception():
print(f"{str(future.exception())} was raised (I do not know where, somewhere)")
else:
print("success (again, I do not know where, exactly)")

# all the threads are finished at that point
print("all threads are done")

I do not know how to get the name of the future which raised the exception (I will ask a new question about that)

How to catch an Exception from a thread

Use a Thread.UncaughtExceptionHandler.

Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread th, Throwable ex) {
System.out.println("Uncaught exception: " + ex);
}
};
Thread t = new Thread() {
@Override
public void run() {
System.out.println("Sleeping ...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Interrupted.");
}
System.out.println("Throwing exception ...");
throw new RuntimeException();
}
};
t.setUncaughtExceptionHandler(h);
t.start();

How to catch exceptions that happened in a python threading.Thread execution?

Try this one.

When you catch it in thread's caller, you can easily email it like you used to do.

Catch a thread's exception in the caller thread in Python

can't catch exception in main thread when other thread active and has try-catch

It's not so much that the exception isn't caught as it is that destroying a joinable thread terminates the process.
So your program terminates before the exception handler can be executed.

If you declare the thread outside the try-catch block, the exception will be caught.

Remember that you also need to join the thread if the exception was thrown.

Catch exception after thread is done

You can use Task with an STA thread (which I assume is what you want).

To do so, you can write some helper methods to start a task on a thread that has been set to STA:

public static class STATask
{
/// <summary>
/// Similar to Task.Run(), except this creates a task that runs on a thread
/// in an STA apartment rather than Task's MTA apartment.
/// </summary>
/// <typeparam name="TResult">The return type of the task.</typeparam>
/// <param name="function">The work to execute asynchronously.</param>
/// <returns>A task object that represents the work queued to execute on an STA thread.</returns>

[NotNull] public static Task<TResult> Run<TResult>([NotNull] Func<TResult> function)
{
var tcs = new TaskCompletionSource<TResult>();

var thread = new Thread(() =>
{
try
{
tcs.SetResult(function());
}

catch (Exception e)
{
tcs.SetException(e);
}
});

thread.SetApartmentState(ApartmentState.STA);
thread.Start();

return tcs.Task;
}

/// <summary>
/// Similar to Task.Run(), except this creates a task that runs on a thread
/// in an STA apartment rather than Task's MTA apartment.
/// </summary>
/// <param name="action">The work to execute asynchronously.</param>
/// <returns>A task object that represents the work queued to execute on an STA thread.</returns>

[NotNull] public static Task Run([NotNull] Action action)
{
var tcs = new TaskCompletionSource<object>(); // Return type is irrelevant for an Action.

var thread = new Thread(() =>
{
try
{
action();
tcs.SetResult(null); // Irrelevant.
}

catch (Exception e)
{
tcs.SetException(e);
}
});

thread.SetApartmentState(ApartmentState.STA);
thread.Start();

return tcs.Task;
}
}

Once you have that, you can easily create an STA task and then use .ContinueWith() to handle exceptions thrown in the task, or use await to catch the exceptions.

(Note: [NotNull] is from Resharper annotations - remove them if you're not using Resharper.)



Related Topics



Leave a reply



Submit