다음을 통해 공유


시간 제한 사용

호출자가 메서드 호출이 완료되기를 기다릴 최대 시간을 지정하려면 시간 제한을 사용합니다.

시간 제한에서는 다음과 같이 메서드 호출에 매개 변수 형식을 사용할 수 있습니다.

server.PerformOperation(timeout)
server.PerformOperation(timeout);

또한 시간 제한은 다음과 같이 서버 클래스에서 속성으로 사용될 수 있습니다.

server.Timeout = timeout
server.PerformOperation()
server.Timeout = timeout;
server.PerformOperation();   

첫 번째 방법에서는 작업과 시간 제한 간의 관계가 보다 분명하기 때문에 대개 이 방법을 사용합니다. 서버 클래스가 비주얼 디자이너와 함께 사용되는 구성 요소가 되도록 디자인된 경우에는 속성을 기반으로 하는 방법이 더 좋은 방법일 수 있습니다.

대개 시간 제한은 정수로 나타냅니다. 그러나 정수로 나타낸 시간 제한은 시간 제한의 단위가 분명하지 않고 시간 단위를 일반적으로 사용되는 밀리초로 변환하기가 어렵기 때문에 사용하기 어렵습니다.

더 좋은 접근 방법은 TimeSpan 구조체를 시간 제한 형식으로 사용하는 것입니다. TimeSpan은 위에서 언급한 정수 제한 시간과 관련된 문제를 해결합니다. 다음 코드 예제에서는 TimeSpan 형식의 시간 제한을 사용하는 방법을 보여 줍니다.

Public Class Server
   Public Sub PerformOperation(timeout As TimeSpan)
      ' Insert code for the method here.
      Console.WriteLine("performing operation with timeout {0}", _
        timeout.ToString())
   End Sub
End Class

public class Server
{
   public void PerformOperation(TimeSpan timeout)
   {
      // Insert code for the method here.
      Console.WriteLine("performing operation with timeout {0}", 
        timeout.ToString());
   }
}
public ref class Server
{
public:
    void PerformOperation(TimeSpan timeout)
    {
        // Insert code for the method here.
        Console::WriteLine("performing operation with timeout {0}",
            timeout.ToString());
    }
};

시간 제한이 TimeSpan(0)으로 설정된 경우 이 메서드는 작업이 즉시 완료되지 않으면 예외를 throw합니다. 시간 제한이 TimeSpan.MaxValue이면 해당 작업은 마치 시간 제한이 설정되지 않은 것처럼 시간 제한 없이 계속 대기합니다. 서버 클래스에서는 이러한 값 중 하나를 지원하지 않아도 되지만 지원되지 않는 시간 제한 값이 지정되면 ArgumentException을 throw해야 합니다.

시간 제한이 만료되고 예외가 throw되면 서버 클래스는 내부 작업을 취소합니다.

기본 시간 제한이 사용되는 경우 서버 클래스에는 사용자가 해당 속성을 지정하지 않을 때 사용되는 시간 제한을 지정하는 정적 속성이 포함되어야 합니다. 다음 코드 예제에서는 기본 시간 제한을 지정하는 속성의 구현을 보여 줍니다.

Class ServerWithDefault
   Private Shared defaultTimeout As New TimeSpan(1000)

   Public Overloads Sub PerformOperation()
      Me.PerformOperation(DefaultOperationTimeout)
   End Sub 

   Public Overloads Sub PerformOperation(timeout As TimeSpan)
      ' Insert code here.
      Console.WriteLine("performing operation with timeout {0}", _
        timeout.ToString())
   End Sub 

   Public Shared ReadOnly Property DefaultOperationTimeout As TimeSpan
      Get
         Return defaultTimeout
      End Get
   End Property
End Class 

class ServerWithDefault
{
   static TimeSpan defaultTimeout = new TimeSpan(1000); 

   public void PerformOperation()
   {
      this.PerformOperation(DefaultOperationTimeout);
   }

   public void PerformOperation(TimeSpan timeout)
   {
      // Insert code here.
      Console.WriteLine("performing operation with timeout {0}", 
        timeout.ToString());
   }

   public static TimeSpan DefaultOperationTimeout
   {
      get
      {
         return defaultTimeout;
      }
   }
}
ref class ServerWithDefault
{
private:
    static TimeSpan defaultTimeout = TimeSpan(1000);

public:
    void PerformOperation()
    {
        this->PerformOperation(DefaultOperationTimeout);
    }

    void PerformOperation(TimeSpan timeout)
    {
        // Insert code here.
        Console::WriteLine("performing operation with timeout {0}",
            timeout.ToString());
    }

    static property TimeSpan DefaultOperationTimeout
    {
       TimeSpan get()
       {
           return defaultTimeout;
       }
    }
};

TimeSpan의 단위까지 시간 제한을 확인할 수 없는 형식에서는 허용할 수 있는 가장 가까운 시간 간격으로 시간 제한을 반올림해야 합니다. 예를 들어, 대기 시간을 1초 단위로만 늘릴 수 있는 형식에서는 가장 가까운 초 수로 반올림해야 합니다. 반올림에 의해 값이 0이 되는 경우에는 이 규칙이 적용되지 않습니다. 이 경우 시간 제한은 가능한 최소 시간 제한으로 올림되어야 합니다. 시간 제한 값이 0일 때 프로세서 사용률이 100%가 되는 상황에서, 0을 올림하면 메서드 호출이 종료되기를 대기하면서 시스템 리소스만 점유하는(busy-wait) 루프를 방지할 수 있습니다.

또한, 시간 제한이 만료되면 오류 코드를 반환하는 대신 예외를 throw하는 것이 좋습니다. 시간 제한 만료는 작업을 완료하지 못했음을 의미하므로 다른 런타임 오류와 마찬가지 방식으로 처리되어야 합니다. 자세한 내용은 예외 디자인 지침을 참조하십시오.

시간 제한이 있는 비동기 작업의 경우에는 작업 결과에 처음 액세스할 때 콜백 함수가 호출되고 예외가 throw되어야 합니다. 다음 코드 예제는 이것을 보여 줍니다.

Sub OnReceiveCompleted(ByVal sender As System.Object, ByVal asyncResult As ReceiveCompletedEventArgs)
   Dim queue As MessageQueue = CType(sender, MessageQueue)
   ' The following code will throw an exception
   ' if BeginReceive has timed out.
   Dim message As Message = queue.EndReceive(asyncResult.AsyncResult)
   Console.WriteLine(("Message: " + CStr(message.Body)))
   queue.BeginReceive(New TimeSpan(1, 0, 0))
End Sub 
void OnReceiveCompleted(Object sender, ReceiveCompletedEventArgs asyncResult)
{
   MessageQueue queue = (MessageQueue) sender;
   // The following code will throw an exception
   // if BeginReceive has timed out.
   Message message = queue.EndReceive(asyncResult.AsyncResult);
   Console.WriteLine("Message: " + (string)message.Body);
queue.BeginReceive(new TimeSpan(1,0,0));
}

Portions Copyright 2005 Microsoft Corporation. All rights reserved.

Portions Copyright Addison-Wesley Corporation. All rights reserved.

디자인 지침에 자세한 내용은 참조를 "Framework 디자인 지침: 규칙, 숙어, 및 재사용에 대 한 패턴입니다.NET 라이브러리"도 서 Krzysztof Cwalina와 Brad Abrams, 게시 Addison-wesley, 2005.

참고 항목

개념

사용 지침

기타 리소스

클래스 라이브러리 개발을 위한 디자인 지침

비동기 프로그래밍 디자인 패턴