다음을 통해 공유


try-catch(C# 참조)

try-catch 문은 try 블록과 각각 다른 예외의 처리기를 지정하는 하나 이상의 catch 절로 구성됩니다.

설명

예외가 throw될 경우 CLR(공용 언어 런타임)에서는 이 예외를 처리하는 catch 문을 찾습니다. 현재 실행되고 있는 메서드에 catch 블록이 없는 경우 CLR은 현재 메서드를 호출한 메서드를 찾는 방법으로 호출 스택을 조사합니다. catch 블록을 찾지 못하면 CLR은 사용자에게 처리되지 않은 예외 메시지를 표시하고 프로그램 실행을 중지합니다.

try 블록에는 예외를 발생시킬 수 있는 보호된 코드가 포함됩니다. 이 블록은 예외가 throw되거나 성공적으로 완료될 때까지 실행됩니다. 예를 들어, 다음 예제와 같이 null 개체를 캐스팅하려고 하면 NullReferenceException 예외가 발생합니다.

object o2 = null;
try
{
    int i2 = (int)o2;   // Error
}

catch 절을 인수 없이 사용하여 모든 형식의 예외를 catch할 수 있지만 이러한 방법은 권장되지 않습니다. 일반적으로 복구할 수 있는 예외만 catch해야 합니다. 따라서 다음 예제와 같이 항상 Exception에서 파생된 개체 인수를 지정해야 합니다.

catch (InvalidCastException e) 
{
}

같은 try-catch 문에서 여러 개의 특정 catch 절을 사용할 수 있습니다. catch 절은 순서대로 검사되므로 이런 경우에는 catch 절의 순서가 중요합니다. 보다 구체적인 예외를 먼저 catch하십시오. 나머지 블록을 실행할 수 없도록 catch 블록의 순서를 지정하면 컴파일러에서 오류가 발생합니다.

throw 문을 catch 블록에 사용하여 catch 문에서 catch한 예외를 다시 throw할 수 있습니다. 다음 예제에서는 IOException 예외로부터 소스 정보를 추출한 후 부모 메서드에 대한 예외를 throw합니다.

catch (FileNotFoundException e)
{
    // FileNotFoundExceptions are handled here.
}
catch (IOException e)
{
    // Extract some information from this exception, and then 
    // throw it to the parent method.
    if (e.Source != null)
        Console.WriteLine("IOException source: {0}", e.Source);
    throw;
}

하나의 예외가 발생하고 다른 예외를 throw할 수 있습니다. 이와 같은 경우에는 다음 예제와 같이 내부 예외로 catch한 예외를 지정합니다.

catch (InvalidCastException e) 
{
    // Perform some action here, and then throw a new exception.
    throw new YourCustomException("Put your error message here.", e);
}

다음 예제와 같이 지정한 조건이 true인 경우 예외로 다시 throw할 수 있습니다.

catch (InvalidCastException e)
{
    if (e.Data == null)
    {
        throw;
    }
    else
    {
        // Take some action.
    }
 }

try 안에서는 그 안에 선언된 변수만 초기화합니다. 그렇지 않을 경우, 블록의 실행이 완료되기 전에 발생할 수 있습니다. 예를 들어 다음 코드 예제에서는 변수 n가 try 블록 내에서 초기화됩니다. Write(n) 문의 try 블록 외부에서 이 변수를 사용하려고 하면 컴파일러 오류가 발생합니다.

static void Main() 
{
    int n;
    try 
    {
        // Do not initialize this variable here.
        n = 123;
    }
    catch
    {
    }
    // Error: Use of unassigned local variable 'n'.
    Console.Write(n);
}

catch에 대한 자세한 내용은 try-catch-finally를 참조하십시오.

Async 메서드에서 예외

비동기 메서드가 표시 됩니다는 비동기 한정자와 일반적으로 하나를 포함 하거나 더 식이나 문에서 기다립니다. Await 식을 적용 하는 await 운영자는 Task 또는 Task. await 식에서 발생할 수 있는 catch 블록 또는 finally 블록.

때 충전을 제어는 await 바뀌게 작업이 완료 될 때까지 비동기 메서드에서 메서드 중 일시 중단 됩니다. 작업이 완료 되 면 실행 메서드를 다시 시작할 수 있습니다. 자세한 내용은 Async 및 Await를 사용한 비동기 프로그래밍(C# 및 Visual Basic)비동기 프로그램의 제어 흐름(C# 및 Visual Basic)를 참조하십시오.

완료 된 작업에 있는 await 적용 faulted 상태로에서 처리 되지 않은 예외가 작업을 반환 하는 메서드를 인해 수 있습니다. 작업 대기 중인 예외가 throw 됩니다. 반환 되는 비동기 프로세스를 취소 하는 경우 작업 또한 취소 된 상태에서 종료할 수 있습니다. 취소 된 작업을 기다리는 throw 된 OperationCanceledException. 비동기 프로세스를 취소 하는 방법에 대 한 자세한 내용은 Async 응용 프로그램 미세 조정(C# 및 Visual Basic).

예외를 catch 하는 작업에서 기다립니다은 try 예외에 연결 된 catch 블록과 catch 블록입니다. 예제를 보려면 "예제" 단원을 참조 하십시오.

바뀌게 async 메서드에서 여러 예외가 발생 하 여 작업이 faulted 상태로의 될 수 있습니다. 예를 들어, 작업 결과에 대 한 호출의 수 Task.WhenAll. 이러한 작업을 기다립니다 때 하나의 예외 catch 되 고 catch 하는 예외를 예측할 수 없습니다. 예제를 보려면 "예제" 단원을 참조 하십시오.

예제

다음 예제의 try 블록에는 예외를 발생시킬 수 있는 ProcessString 메서드 호출이 포함되어 있습니다. catch 절에는 단순히 화면에 메시지를 표시하는 예외 처리기가 포함되어 있습니다. MyMethod 내에서 throw 문이 호출되면 시스템에서 catch 문을 찾아 Exception caught라는 메시지를 표시합니다.

    class TryFinallyTest
{
    static void ProcessString(string s)
    {
        if (s == null)
        {
            throw new ArgumentNullException();
        }
    }

    static void Main()
    {
        string s = null; // For demonstration purposes. 

        try
        {            
            ProcessString(s);
        }

        catch (Exception e)
        {
            Console.WriteLine("{0} Exception caught.", e);
        }
    }
}
    /*
    Output:
    System.ArgumentNullException: Value cannot be null.
       at TryFinallyTest.Main() Exception caught.
     * */

다음 예제에서는 두 개의 catch 블록에 사용 되는 고 앞에 나오는 더 구체적인 예외가 catch 됩니다.

가장 구체적인 예외를 catch 할 수에서 throw 문을 대체할 수 있습니다 ProcessString 다음 문을 사용: throw new Exception().

예제에서는 최소한 관련 catch 블록을 먼저 배치 하는 경우 다음과 같은 오류 메시지가 나타납니다: A previous catch clause already catches all exceptions of this or a super type ('System.Exception').

class ThrowTest3
{
    static void ProcessString(string s)
    {
        if (s == null)
        {
            throw new ArgumentNullException();
        }
    }

    static void Main()
    {
        try
        {
            string s = null;
            ProcessString(s);
        }
        // Most specific: 
        catch (ArgumentNullException e)
        {
            Console.WriteLine("{0} First exception caught.", e);
        }
        // Least specific: 
        catch (Exception e)
        {
            Console.WriteLine("{0} Second exception caught.", e);
        }
    }
}
/*
 Output:
 System.ArgumentNullException: Value cannot be null.
 at Test.ThrowTest3.ProcessString(String s) ... First exception caught.
*/

다음 예제에서는 예외를 처리에 대해 async 메서드를 보여 줍니다. 비동기 작업이 throw 한 예외를 catch 하려면 배치는 await 식에는 try 차단 하 고 예외를 catch 한 catch 블록.

주석 처리를 제거는 throw new Exception 선 예외 처리를 보여 주는 예제입니다. 작업의 IsFaulted 속성이 True, 작업의 Exception.InnerException 속성에 예외를 설정 하 고는 예외가 catch 되는 catch 블록입니다.

주석 표시는 throw new OperationCancelledException 어떻게 보여 줄 때 여 cancelan 비동기 프로세스입니다. 작업의 IsCanceled 속성이 true, 및 예외가 catch 되는 catch 블록입니다. 이 예제와 작업의 적용 되지 않는 몇 가지 상황에서 IsFaulted 속성이 true 및 IsCanceled 로 설정 된 false.

        public async Task DoSomethingAsync()
        {
            Task<string> theTask = DelayAsync();

            try
            {
                string result = await theTask;
                Debug.WriteLine("Result: " + result);
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Exception Message: " + ex.Message);
            }
            Debug.WriteLine("Task IsCanceled: " + theTask.IsCanceled);
            Debug.WriteLine("Task IsFaulted:  " + theTask.IsFaulted);
            if (theTask.Exception != null)
            {
                Debug.WriteLine("Task Exception Message: "
                    + theTask.Exception.Message);
                Debug.WriteLine("Task Inner Exception Message: "
                    + theTask.Exception.InnerException.Message);
            }
        }

        private async Task<string> DelayAsync()
        {
            await Task.Delay(100);

            // Uncomment each of the following lines to 
            // demonstrate exception handling. 

            //throw new OperationCanceledException("canceled");
            //throw new Exception("Something happened.");
            return "Done";
        }

        // Output when no exception is thrown in the awaited method: 
        //   Result: Done 
        //   Task IsCanceled: False 
        //   Task IsFaulted:  False 

        // Output when an Exception is thrown in the awaited method: 
        //   Exception Message: Something happened. 
        //   Task IsCanceled: False 
        //   Task IsFaulted:  True 
        //   Task Exception Message: One or more errors occurred. 
        //   Task Inner Exception Message: Something happened. 

        // Output when a OperationCanceledException or TaskCanceledException 
        // is thrown in the awaited method: 
        //   Exception Message: canceled 
        //   Task IsCanceled: True 
        //   Task IsFaulted:  False

다음 예제에서는 예외 처리를 여러 작업에 여러 예외가 발생할 수 있습니다 위치를 보여 줍니다. try 블록 호출에 의해 반환 되는 작업을 잠그고 Task.WhenAll. Whenall에 적용 되는 세 가지 작업이 완료 되 면 작업이 완료 되었습니다.

각각의 세 가지 작업 중에 예외가 발생합니다. catch 에 있는 예외 블록 반복의 Exception.InnerExceptions 속성에서 반환 된 작업의 Task.WhenAll.

public async Task DoMultipleAsync()
{
    Task theTask1 = ExcAsync(info: "First Task");
    Task theTask2 = ExcAsync(info: "Second Task");
    Task theTask3 = ExcAsync(info: "Third Task");

    Task allTasks = Task.WhenAll(theTask1, theTask2, theTask3);

    try
    {
        await allTasks;
    }
    catch (Exception ex)
    {
        Debug.WriteLine("Exception: " + ex.Message);
        Debug.WriteLine("Task IsFaulted: " + allTasks.IsFaulted);
        foreach (var inEx in allTasks.Exception.InnerExceptions)
        {
            Debug.WriteLine("Task Inner Exception: " + inEx.Message);
        }
    }
}

private async Task ExcAsync(string info)
{
    await Task.Delay(100);

    throw new Exception("Error-" + info);
}

// Output: 
//   Exception: Error-First Task 
//   Task IsFaulted: True 
//   Task Inner Exception: Error-First Task 
//   Task Inner Exception: Error-Second Task 
//   Task Inner Exception: Error-Third Task

C# 언어 사양

자세한 내용은 C# 언어 사양을 참조하세요. C# 언어 사양은 C# 구문 및 사용법에 대한 신뢰할 수 있는 소스입니다.

참고 항목

작업

방법: 명시적으로 예외 Throw

참조

C# 키워드

Try, Throw 및 Catch 문(C++)

예외 처리문(C# 참조)

throw(C# 참조)

try-finally(C# 참조)

개념

C# 프로그래밍 가이드

기타 리소스

C# 참조