您的位置:首页 > 其它

应用多线程:解决等待超时问题

2008-09-10 21:08 204 查看
我和老米曾经讨论过等待超时的问题觉得是比较挺常用的代码,所以在这里和大家分享一下。我和老米的思路略有不同这里没有孰优孰略,只是习惯差异而已。

我们日常工作中常会遇到这种场景:数据库、远程webservice、串口设备等等连接失败,或其他需要长时间等待才能返回错误信息的情况。这时我们需要设定一个超时时间如果出现问题能够及时反馈给用户。虽然我们给数据库或webservice把超时设定很短,但这样做不灵活因为有些操作本身就是很耗时的。因此我们应该利用多线程来解决这个问题。

其实这个问题很好解决,会超时的操作用异步执行(异步委托或者线程池),用户主线程进行等待通知(ManualResetEvent)。如果用户在超时时间能都没等到就会激发超时事件通知用户。看代码吧一目了然:

public class TimeoutChecker

{

long _timeout; //超时时间

Action _proc; //会超时的代码

Action _procHandle; //处理超时

Action _timeoutHandle; //超时后处理事件

ManualResetEvent _event = new ManualResetEvent(false);

public TimeoutChecker(Action proc, Action timeoutHandle)

{

this._proc = proc;

this._timeoutHandle = timeoutHandle;

this._procHandle = delegate

{

//计算代码执行的时间

Stopwatch sw = new Stopwatch();

sw.Start();

if (this._proc != null)

this._proc();

sw.Stop();

//如果执行时间小于超时时间则通知用户线程

if (sw.ElapsedMilliseconds < this._timeout && this._event != null)

{

this._event.Set();

}

};

}

public bool Wait(long timeout)

{

this._timeout = timeout;

//异步执行

this._procHandle.BeginInvoke(null, null);

//如果在规定时间内没等到通知则为false

bool flag = this._event.WaitOne((int)timeout, false);

if (!flag)

{

//触发超时时间

if (this._timeoutHandle != null)

this._timeoutHandle();

}

this.Dispose();

return flag;

}

private void Dispose()

{

if(this._event != null)

this._event.Close();

this._event = null;

this._proc = null;

this._procHandle = null;

this._timeoutHandle = null;

}

}

代码很简单,下面是调用例子

TimeoutChecker we = new TimeoutChecker(delegate

{

using (SqlConnection conn = new SqlConnection())

{

conn.ConnectionString = "server=.;database=test;uid=sa;pwd=s";

conn.Open();

}}, delegate { Console.WriteLine("数据库不存在"); });

if (we.Wait(200))

Console.WriteLine("链接成功");

是不是很方便啊。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: