超时的使用

使用超时指定调用方最多愿意花多长时间等待方法调用完成。

超时可以是方法调用参数的形式,如下所示。

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),当没有立即完成操作时,方法应引发异常。 如果超时为 TimeSpan.MaxValue,则操作应永远等待而不超时,就像没有设置超时一样。 支持这两个值不需要服务器类,但是如果指定了不受支持的超时值,服务器类应引发 ArgumentException

如果超时过期并且引发了异常,服务器类应取消基础操作。

如果使用了默认超时,服务器类应包含一个静态属性,用以指定当用户没有指定超时时使用的超时。 下面的代码示例演示如何实现指定默认超时的属性。

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 解析的类型应将超时舍入到可以提供的最接近的间隔。 例如,只能按一秒的增量等待的类型应该舍入到最接近的秒。 此规则的例外情况是当值向下舍入到零时。 这种情况下,超时应向上舍入到可能的最小超时。 避免舍入为零可防止出现“繁忙等待”循环,即零超时值导致 100% 的处理器使用。

另外,建议在超时过期时引发异常而不是返回错误代码。 超时过期意味着操作未能成功完成,因此应该按任何其他运行时错误处理。 有关更多信息,请参见异常设计准则

对于具有超时的异步操作,在首次访问操作结果时,应该调用回调函数并引发异常。 下面的代码示例中阐释了这一点。

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));
}

部分版权所有 2005 Microsoft Corporation。 保留所有权利。

部分版权所有 Addison-Wesley Corporation。 保留所有权利。

设计指引的详细信息,请参阅"框架设计准则: 公约、 成语和可重复使用的模式。网络图书馆"书 Krzysztof Cwalina 和布拉德 · 艾布拉姆斯,2005年艾迪生 - 韦斯利,发表。

请参见

概念

使用准则

其他资源

类库开发的设计准则

异步编程设计模式