《C#并发编程经典实例》—— 超时

简介:

声明:本文是《C#并发编程经典实例》的样章,感谢图灵授权并发编程网站发布样章,禁止以任何形式转载此文。

问题
我们希望事件能在预定的时间内到达,即使事件不到达,也要确保程序能及时进行响应。
通常此类事件是单一的异步操作(例如,等待 Web 服务请求的响应)。

解决方案
Timeout 操 作 符 在 输 入 流 上 建 立 一 个 可 调 节 的 超 时 窗 口。 一 旦 新 的 事 件 到 达, 就 重 置 超 时 窗 口。 如 果 超 过 期 限 后 事 件 仍 没 到 达,Timeout 操 作 符 就 结 束 流, 并 产 生 一 个 包 含 TimeoutException 的 OnError 通知。

下面的代码向一个域名发出 Web 请求,并使用 1 秒作为超时值:

private void Button_Click(object sender, RoutedEventArgs e)
{
var client = new HttpClient();
client.GetStringAsync("http://www.example.com/").ToObservable()
.Timeout(TimeSpan.FromSeconds(1))
.Subscribe(
x => Trace.WriteLine(DateTime.Now.Second + ": Saw " + x.Length), ex => Trace.WriteLine(ex));
}

Timeout 非常适用于异步操作,例如 Web 请求,但它也能用于任何事件流。下面的例子在
监视鼠标移动时使用 Timeout,使用起来更加简单:

private void Button_Click(object sender, RoutedEventArgs e)
{
Observable.FromEventPattern<MouseEventHandler, MouseEventArgs>(
handler => (s, a) => handler(s, a), handler => MouseMove += handler, handler => MouseMove -= handler)
.Select(x => x.EventArgs.GetPosition(this))
.Timeout(TimeSpan.FromSeconds(1))
.Subscribe(
x => Trace.WriteLine(DateTime.Now.Second + ": Saw " + (x.X + x.Y)), ex => Trace.WriteLine(ex));
}

我移动了一下鼠标,然后停止 1 秒,得到如下结果:

16: Saw 180
16: Saw 178
16: Saw 177
16: Saw 176
System.TimeoutException: The operation has timed out.

值得注意的是,一旦向 OnError 发送 TimeoutException,整个事件流就结束了,不会继续 传来鼠标移动事件。为了阻止这种情况出现,Timeout 操作符具有重载方式,在超时发生 时用另一个流来替代,而不是抛出异常并结束流。

下面的例子,在超时之前观察鼠标移动,超时发生后进行切换,观察鼠标点击:

private void Button_Click(object sender, RoutedEventArgs e)
{
var clicks = Observable.FromEventPattern
<MouseButtonEventHandler, MouseButtonEventArgs>(
handler => (s, a) => handler(s, a), handler => MouseDown += handler, handler => MouseDown -= handler)
.Select(x => x.EventArgs.GetPosition(this));

Observable.FromEventPattern<MouseEventHandler, MouseEventArgs>(
handler => (s, a) => handler(s, a), handler => MouseMove += handler, handler => MouseMove -= handler)
.Select(x => x.EventArgs.GetPosition(this))
.Timeout(TimeSpan.FromSeconds(1), clicks)
.Subscribe(
x => Trace.WriteLine(
DateTime.Now.Second + “: Saw ” + x.X + “,” + x.Y), ex => Trace.WriteLine(ex));
}

我先移动一下鼠标,停止 1 秒,然后在两个不同的位置点击。下面的输出表明,超时发生
前鼠标移动事件在进行快速移动,超时后变成两个鼠标点击事件:

49: Saw 95,39
49: Saw 94,39
49: Saw 94,38
49: Saw 94,37
53: Saw 130,141
55: Saw 469,4

讨论
Timeout 操作符对优秀的程序来说是十分必要的,因为我们总是希望程序能及时响应,即 使外部环境不理想。它可用于任何事件流,尤其是在异步操作时。需要注意,此时内部的 操作并没有真正取消,操作将继续执行,直到成功或失败。

相关文章
|
C#
C#高性能大容量SOCKET并发(六):超时Socket断开(守护线程)和心跳包
原文:C#高性能大容量SOCKET并发(六):超时Socket断开(守护线程)和心跳包 守护线程 在服务端版Socket编程需要处理长时间没有发送数据的Socket,需要在超时多长时间后断开连接,我们需要独立一个线程(DaemonT...
2859 0
|
C#
C# UdpClient 设置超时时间
/********************************************************************** * C# UdpClient 设置超时时间 * 说明: * 网络通信中设置超时时间是常有的时,记录UDP获取、发送超时设置方法。
1492 0
|
C#
C# 中通过CancellationTokenSource实现对超时任务的取消
在基于Task的任务执行过程中,我们通常使用CancellationTokenSource来实现任务取消,首先看一个简单的例子。 var cancelTokenSource = newCancellationTokenSource(); Task.
2235 0
|
XML C# 数据格式
C# post数据时 出现如下错误: System.Net.WebException: 操作超时
net(客户端)调用IIS(服务端)出现503后,就报操作超时错误问题描述: 服务端环境: IIS 客户端环境: windowsxp + iis + .net 调用时出现如下错误: System.Net.WebException: 远程服务器返回错误: (503) 服务器不可用。
6944 0
|
C#
C#如何控制方法的执行时间,超时则强制退出方法执行
转载:http://outofmemory.cn/code-snippet/1762/C-how-control-method-zhixingshijian-chaoshi-ze-force-quit-method-execution/comments1         http://www.
1791 0
|
C#
C#用WebClient下载File时操作超时的问题
原文:C#用WebClient下载File时操作超时的问题 今天很SB,被这个问题卡住了。那段代码也是网上找的。结果发现只能下载一个文件,第二次下载的时候就会出现“操作超时”的问题。   这个是原代码: System.
1367 0
|
17天前
|
开发框架 前端开发 .NET
C#编程与Web开发
【4月更文挑战第21天】本文探讨了C#在Web开发中的应用,包括使用ASP.NET框架、MVC模式、Web API和Entity Framework。C#作为.NET框架的主要语言,结合这些工具,能创建动态、高效的Web应用。实际案例涉及企业级应用、电子商务和社交媒体平台。尽管面临竞争和挑战,但C#在Web开发领域的前景将持续拓展。