超时的使用
使用超时指定调用方最多愿意花多长时间等待方法调用完成。
超时可以是方法调用参数的形式,如下所示。
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年艾迪生 - 韦斯利,发表。