zl程序教程

您现在的位置是:首页 >  后端

当前栏目

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

2023-09-11 14:16:13 时间

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

转载自 并发编程网 - ifeve.com
多线程概述 一.线程相关概念 (1)程序 是为了完成特定任务、用某种语言编写的一组指令的集合。简单的说就是我们写的代码。 (2)进程 ①进程是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程; ②进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。 比如我们使用的QQ,就启动了一个进程,操作系统就会为该进程分配内存空间。当我们使用迅雷,又启动了一个进程,操作系统将为迅雷分配新的内存空间。