다른 스레드에서 발생한 예외 포착
내 방법 중 하나 ( Method1
)는 새 스레드를 생성합니다. 해당 스레드는 메서드 ( Method2
)를 실행하고 예외 중에 예외가 발생합니다. 호출 메서드 ( Method1
) 에 대한 예외 정보를 가져와야합니다.
어떻게 Method1
든 던져진 이 예외를 잡을 수 Method2
있습니까?
에서 .NET 4 이상, 당신은 사용할 수 있습니다 Task<T>
새 스레드를 만드는 대신 클래스를. 그런 다음 .Exceptions
작업 개체의 속성을 사용하여 예외를 가져올 수 있습니다 . 두 가지 방법이 있습니다.
별도의 메서드에서 : // 일부 작업의 스레드 에서 예외를 처리 합니다.
class Program { static void Main(string[] args) { Task<int> task = new Task<int>(Test); task.ContinueWith(ExceptionHandler, TaskContinuationOptions.OnlyOnFaulted); task.Start(); Console.ReadLine(); } static int Test() { throw new Exception(); } static void ExceptionHandler(Task<int> task) { var exception = task.Exception; Console.WriteLine(exception); } }
같은 방법으로 : // 호출자의 스레드 에서 예외를 처리 합니다.
class Program { static void Main(string[] args) { Task<int> task = new Task<int>(Test); task.Start(); try { task.Wait(); } catch (AggregateException ex) { Console.WriteLine(ex); } Console.ReadLine(); } static int Test() { throw new Exception(); } }
당신이 얻는 예외는 AggregateException
. 모든 실제 예외는 ex.InnerExceptions
재산을 통해 이용 가능 합니다.
.NET 3.5 에서는 다음 코드를 사용할 수 있습니다.
// 자식 스레드 에서 예외를 처리 합니다.
class Program { static void Main(string[] args) { Exception exception = null; Thread thread = new Thread(() => SafeExecute(() => Test(0, 0), Handler)); thread.Start(); Console.ReadLine(); } private static void Handler(Exception exception) { Console.WriteLine(exception); } private static void SafeExecute(Action test, Action<Exception> handler) { try { test.Invoke(); } catch (Exception ex) { Handler(ex); } } static void Test(int a, int b) { throw new Exception(); } }
또는 // 호출자의 스레드 에서 예외를 처리 합니다.
class Program { static void Main(string[] args) { Exception exception = null; Thread thread = new Thread(() => SafeExecute(() => Test(0, 0), out exception)); thread.Start(); thread.Join(); Console.WriteLine(exception); Console.ReadLine(); } private static void SafeExecute(Action test, out Exception exception) { exception = null; try { test.Invoke(); } catch (Exception ex) { exception = ex; } } static void Test(int a, int b) { throw new Exception(); } }
Method1에서 예외를 포착 할 수 없습니다. 그러나 Method2에서 예외를 포착하여 원래 실행 스레드가 읽고 작업 할 수있는 변수에 기록 할 수 있습니다.
서로 다른 스레드간에 데이터를 공유하는 가장 간단한 방법은 shared data
다음과 같습니다 (일부는 의사 코드 임).
class MyThread
{
public string SharedData;
public void Worker()
{
...lengthy action, infinite loop, etc...
SharedData = "whatever";
...lengthy action...
return;
}
}
class Program
{
static void Main()
{
MyThread m = new MyThread();
Thread WorkerThread = new Thread(m.Worker);
WorkerThread.Start();
loop//or e.g. a Timer thread
{
f(m.SharedData);
}
return;
}
}
You can read about this method in this nice introduction about multithreading, however, I preferred to read about this in the O'Reilly book C# 3.0 in a nutshell
, by the brothers Albahari (2007), which is also freely accessible on Google Books, just like the newer version of the book, because it also covers thread pooling, foreground versus background threads, etc etc, with nice and simple example code. (Disclaimer: I own a worn-out copy of this book)
In case you are making a WinForms application, the use of shared data is especially handy, because the WinForm controls are not thread-safe. Using a callback to pass data from the worker thread back to a WinForm control the main UI thread needs ugly code with Invoke()
to make that control thread-safe. Using shared data instead, and the single-threaded System.Windows.Forms.Timer
, with a short Interval
of say 0.2 seconds, you can easily send information from the worker thread to the control without Invoke
.
I had a particular problem in that I wanted to use items, containing controls, from an integration test suite, so have to create an STA thread. The code I ended up with is as follows, put here in case others have the same issue.
public Boolean? Dance(String name) {
// Already on an STA thread, so just go for it
if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA) return DanceSTA(name);
// Local variable to hold the caught exception until the caller can rethrow
Exception lException = null;
Boolean? lResult = null;
// A gate to hold the calling thread until the called thread is done
var lGate = new ManualResetEvent(false);
var lThreadStart = new ThreadStart(() => {
try {
lResult = DanceSTA(name);
} catch (Exception ex) {
lException = ex;
}
lGate.Set();
});
var lThread = new Thread(lThreadStart);
lThread.SetApartmentState(ApartmentState.STA);
lThread.Start();
lGate.WaitOne();
if (lException != null) throw lException;
return lResult;
}
public Boolean? DanceSTA(String name) { ... }
This is a direct paste of the code as-is. For other uses I would recommend supplying an action or function as a parameter and invoking that on the thread instead of hard-coding the called method.
참고URL : https://stackoverflow.com/questions/5983779/catch-exception-that-is-thrown-in-different-thread
'programing tip' 카테고리의 다른 글
Rmarkdown에 \ newpage를 현명하게 추가하는 방법은 무엇입니까? (0) | 2020.08.12 |
---|---|
.h.gch 파일이란 무엇입니까? (0) | 2020.08.12 |
Go에서 fmt.Println ()과 println ()의 차이점은 무엇입니까? (0) | 2020.08.12 |
React Enzyme은 두 번째 (또는 n 번째) 노드를 찾습니다. (0) | 2020.08.12 |
data.frame 열 이름을 함수에 전달 (0) | 2020.08.12 |