应用多线程:解决等待超时问题
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("链接成功");
是不是很方便啊。
我们日常工作中常会遇到这种场景:数据库、远程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("链接成功");
是不是很方便啊。
相关文章推荐
- ORA-02049: 超时: 分布式事务处理等待锁 问题的解决
- Java项目中超时问题解决方案汇总--解决cxf 时间 等待问题 bug~~~~
- 应用多线程:解决等待超时问题
- 编译存储过程 等待锁定对象 时超时问题解决
- oracle 编译存储过程 等待锁定对象 时超时问题解决
- 【问题解决】eclipse中tomcat或JBOSS的启动报45秒超时
- Mac系统打开应用程序文件夹的方法+解决Android studio出现fetching android sdk component超时打不开的问题
- 解决FastCGI 进程超过了配置的活动超时时限的问题.doc
- AjaxPro实现异步调用,解决浏览器假死及超时问题
- [turn]调用webservice超时问题的解决
- 解决使用HttpWebRequest时总是提示登陆超时的问题
- tomcat在eclipse中启动超时的问题解决
- app令牌登录解决session超时重登陆的问题
- WebClient的超时问题及解决
- 蛙蛙推荐:一套.net窗体身份验证方案(解决了防止用户重复登陆,session超时等问题)
- 解决FastCGI 进程超过了配置的活动超时时限的问题
- 蛙蛙推荐:一套.net窗体身份验证方案(解决了防止用户重复登陆,session超时等问题)
- Eclipse启动Tomcat超时问题的解决方法
- MySQL查询超时问题的解决
- 使用wordpress导出XML格式备份时超时问题的解决