zoukankan      html  css  js  c++  java
  • 指令等待模型

    代码有所修改,但暂时没时间,提一下是关于OnWaitComplete和OnWaitTimeout以及IsWaiting属性,为了在Onxx方法中可以继续下一个等待,而先将IsWaiting置false,再调用Onxx方法

    a. 单等待模型

    用于需要等待某事件的响应或定时等待。在等待时间比较长的时候可考虑使用。

    using System;
    using System.Threading;
    
    namespace Hu
    {
        public abstract class TimeoutHandler : IDisposable
        {
            AutoResetEvent _auto = new AutoResetEvent(false);
    
            public bool IsWaiting
            {
                get { return _isWaiting; }
            }
            protected volatile bool _isWaiting = false;
    
            public int Timeout
            {
                get { return _timeout; }
                set
                {
                    if (value < 0 && value != -1)
                        throw new ArgumentException("值必须为小于int.MaxValue的非负数或为-1");
                }
            }
            protected int _timeout;
    
            protected TimeoutHandler()
                : this(10000)
            { }
    
            protected TimeoutHandler(int timeoutMs)
            {
                _timeout = timeoutMs;
            }
    
            ~TimeoutHandler()
            {
                if (_auto != null)
                    _auto.Dispose();
            }
    
            /// <summary>
            /// 异步进行<see cref="Timeout"/>指定毫秒数的等待。
            /// 返回true表示操作成功,false表示前一次等待未结束。
            /// </summary>
            /// <param name="info"></param>
            /// <returns></returns>
            public bool DoWait(object info = null)
            {
                if (true == IsWaiting)
                    return false;
    
                _isWaiting = true;
                Action<object> waitDel = Wait;
                waitDel.BeginInvoke(info, new AsyncCallback(ar =>
                {
                    try
                    {
                        Action<object> del = ar.AsyncState as Action<object>;
                        del?.EndInvoke(ar);
                    }
                    catch
                    { }
                    _isWaiting = false;
                }), waitDel);
    
                return true;
            }
    
            /// <summary>
            /// 结束当前等待。
            /// 返回true表示操作成功,反之操作失败或当前不在异步等待状态(通过<see cref="IsWaiting"/>获取)。
            /// </summary>
            /// <returns></returns>
            public bool CeaseWait()
            {
                if (true == IsWaiting)  // 防止没有异步等待时的误操作影响后续判断
                    return _auto.Set();
    
                return false;
            }
    
            public void Dispose()
            {
                _auto.Dispose();
            }
    
            /// <summary>
            /// 等待超时
            /// </summary>
            /// <param name="info"></param>
            protected abstract void OnWaitTimeout(object info);
    
            /// <summary>
            ///<see cref="Timeout"/>前,结束了等待
            /// </summary>
            /// <param name="info"></param>
            protected virtual void OnWaitCompleted(object info)
            { }
    
            private void Wait(object info)
            {
                bool succeed = _auto.WaitOne(Timeout);
                if (true == succeed)
                    OnWaitCompleted(info);
                else
                    OnWaitTimeout(info);
            }
    
        }
    }
    View Code

    b. 多等待模型

    用于需要在短时间等待若干事件的响应进行后续操作的情况。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading;
    
    namespace Hu
    {
        public class TaskInfo : IEquatable<TaskInfo>
        {
            public string TaskID
            {
                get;
                internal set;
            }
    
            public int Timeout
            {
                get;
                internal set;
            }
    
            public bool IsTimeout
            {
                get;
                internal set;
            }
    
            public bool IsCanceled
            {
                get;
                internal set;
            }
    
            public TaskInfo(string vTaskID, int vTimeoutMs)
            {
                if (string.IsNullOrEmpty(vTaskID))
                    throw new ArgumentNullException("vTaskID");
    
                TaskID = vTaskID;
    
                if (vTimeoutMs < 0 && vTimeoutMs != -1)
                    throw new ArgumentException("vTimeoutMs必须为小于int.MaxValue的非负数");
    
                Timeout = vTimeoutMs;
            }
    
            public bool Equals(TaskInfo other)
            {
                if (null == other)
                    return false;
    
                return TaskID.CompareTo(other.TaskID) == 0;
            }
    
            public override bool Equals(object obj)
            {
                TaskInfo ti = obj as TaskInfo;
                if (null == ti)
                    return false;
    
                return TaskID.CompareTo(ti.TaskID) == 0;
            }
    
            public override int GetHashCode()
            {
                return base.GetHashCode();
            }
        }
    
        public abstract class MultiTimeoutHandler
        {
            readonly object _syncLock = new object();
            protected List<TaskInfo> _lstTaskInfo = new List<TaskInfo>();
    
            public bool DoWait(TaskInfo info)
            {
                if (false == Monitor.TryEnter(_syncLock, 2000))
                    return false;
    
                try
                {
                    var ti = _lstTaskInfo.FirstOrDefault(t => t.TaskID.CompareTo(info.TaskID) == 0);
                    if (ti != null)
                        return false;
    
                    _lstTaskInfo.Add(info);
                    Action<TaskInfo> ta = WaitTask;
                    ta.BeginInvoke(info, new AsyncCallback(ar =>
                    {
                        try
                        {
                            Action<TaskInfo> del = ar.AsyncState as Action<TaskInfo>;
                            del.EndInvoke(ar);
                        }
                        catch { }
                    }), ta);
                }
                finally
                {
                    Monitor.Exit(_syncLock);
                }
    
                return true;
            }
    
            public bool CeaseWait(string taskID)
            {
                if (false == Monitor.TryEnter(_syncLock, 2000))
                    return false;
    
                try
                {
                    var ti = _lstTaskInfo.FirstOrDefault(t => t.TaskID.CompareTo(taskID) == 0);
                    if (ti == null)
                        throw new ArgumentException("没有与指定任务标识匹配的任务信息", "taskID");
    
                    ti.IsCanceled = true;
    
                    return true;
                }
                finally
                {
                    Monitor.Exit(_syncLock);
                }
            }
    
            protected abstract void OnWaitTimeout(TaskInfo info);
    
            protected virtual void OnWaitCompleted(TaskInfo info)
            { }
    
            private void WaitTask(TaskInfo info)
            {
                DateTime st = DateTime.Now;
                SpinWait sw = new SpinWait();
                while (false == info.IsCanceled)
                {
                    sw.SpinOnce();
                    info.IsTimeout = (DateTime.Now - st >= TimeSpan.FromMilliseconds(info.Timeout));
                    if (true == info.IsTimeout)
                        break;
                }
    
                if (true == info.IsTimeout)
                    WaitTimeout(info);
                else
                    WaitCompleted(info);
            }
    
            private void WaitTimeout(TaskInfo info)
            {
                lock (_syncLock)
                {
                    bool removed = _lstTaskInfo.Remove(info);
                }
    
                OnWaitTimeout(info);
            }
    
            private void WaitCompleted(TaskInfo info)
            {
                lock (_syncLock)
                {
                    bool removed = _lstTaskInfo.Remove(info);
                }
    
                OnWaitCompleted(info);
            }
        }
    
        public class TestC : MultiTimeoutHandler
        {
            protected override void OnWaitTimeout(TaskInfo info)
            {
                Console.WriteLine("Timeout: {0}|{1}|{2}|{3}", info.TaskID, info.Timeout, info.IsCanceled, info.IsTimeout);
            }
        }
    }
    View Code

    有些时候,比如客户端使用udp向服务端发送命令后,可能需要客户端在一段时间内没接收到服务端应答时进行重发等操作,可以考虑a模型;a模型也可以用作一个闹钟。上述模型避免了外部类注册回调或事件,提供了类间的松散耦合。

  • 相关阅读:
    prototype.js超强的javascript类库
    MySQL Server Architecture
    Know more about RBA redo block address
    MySQL无处不在
    利用Oracle Enterprise Manager Cloud Control 12c创建DataGuard Standby
    LAMP Stack
    9i中DG remote archive可能导致Primary Database挂起
    Oracle数据库升级与补丁
    Oracle为何会发生归档日志archivelog大小远小于联机重做日志online redo log size的情况?
    Oracle Ksplice如何工作?How does Ksplice work?
  • 原文地址:https://www.cnblogs.com/xuanhu/p/12594284.html
Copyright © 2011-2022 走看看