|
| 1 | +using System; |
| 2 | +using System.Collections.Generic; |
| 3 | +using System.IO; |
| 4 | +using System.Linq; |
| 5 | +using System.Runtime.InteropServices; |
| 6 | +using System.Text; |
| 7 | +using System.Threading.Tasks; |
| 8 | + |
| 9 | +namespace QuantBox.XAPI.Callback |
| 10 | +{ |
| 11 | + public class BaseApi : IDisposable |
| 12 | + { |
| 13 | + protected Proxy proxy; |
| 14 | + protected IntPtr Handle = IntPtr.Zero; |
| 15 | + protected Queue _Queue; |
| 16 | + private string _Path; |
| 17 | + |
| 18 | + protected XCall _XRespone; |
| 19 | + |
| 20 | + protected object locker = new object(); |
| 21 | + |
| 22 | + public bool IsConnected { get; protected set; } |
| 23 | + private int _reconnect; |
| 24 | + public int Reconnect |
| 25 | + { |
| 26 | + get { return _reconnect; } |
| 27 | + set { |
| 28 | + _reconnect = value; |
| 29 | + _Timer.Elapsed -= _Timer_Elapsed; |
| 30 | + if (_reconnect > 1000 * 10) |
| 31 | + { |
| 32 | + _Timer.Elapsed += _Timer_Elapsed; |
| 33 | + _Timer.Interval = _reconnect; |
| 34 | + } |
| 35 | + _Timer.Enabled = _reconnect > 1000 * 10; |
| 36 | + } |
| 37 | + } |
| 38 | + |
| 39 | + public ServerInfoField Server; |
| 40 | + public UserInfoField User; |
| 41 | + |
| 42 | + public DelegateOnConnectionStatus OnConnectionStatus; |
| 43 | + public DelegateOnRtnError OnRtnError; |
| 44 | + |
| 45 | + public RspUserLoginField UserLoginField; |
| 46 | + |
| 47 | + |
| 48 | + private System.Timers.Timer _Timer = new System.Timers.Timer(); |
| 49 | + |
| 50 | + public BaseApi(string path1,Queue queue) |
| 51 | + { |
| 52 | + _Path = path1; |
| 53 | + |
| 54 | + // 这里是因为回调函数可能被GC回收 |
| 55 | + _XRespone = _OnRespone; |
| 56 | + _Queue = queue; |
| 57 | + |
| 58 | + Reconnect = 0; |
| 59 | + } |
| 60 | + |
| 61 | + void _Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) |
| 62 | + { |
| 63 | + // 定时检查是否需要销毁对象重连 |
| 64 | + if(!IsConnected) |
| 65 | + { |
| 66 | + Disconnect(); |
| 67 | + Connect(); |
| 68 | + } |
| 69 | + } |
| 70 | + |
| 71 | + |
| 72 | + ~BaseApi() |
| 73 | + { |
| 74 | + Dispose(false); |
| 75 | + } |
| 76 | + |
| 77 | + private bool disposed; |
| 78 | + |
| 79 | + // 一定要先调用API的,再调用队列的,否则会出错 |
| 80 | + public void Dispose() |
| 81 | + { |
| 82 | + Dispose(true); |
| 83 | + GC.SuppressFinalize(this); |
| 84 | + } |
| 85 | + |
| 86 | + protected virtual void Dispose(bool disposing) |
| 87 | + { |
| 88 | + if (!disposed) |
| 89 | + { |
| 90 | + if (disposing) |
| 91 | + { |
| 92 | + // Free other state (managed objects). |
| 93 | + } |
| 94 | + // Free your own state (unmanaged objects). |
| 95 | + // Set large fields to null. |
| 96 | + Disconnect(); |
| 97 | + disposed = true; |
| 98 | + } |
| 99 | + //base.Dispose(disposing); |
| 100 | + } |
| 101 | + |
| 102 | + public virtual void Connect() |
| 103 | + { |
| 104 | + lock(locker) |
| 105 | + { |
| 106 | + // XSpeed多次连接出问题,发现会生成多次 |
| 107 | + if (proxy != null) |
| 108 | + return; |
| 109 | + |
| 110 | + proxy = new Proxy(_Path); |
| 111 | + |
| 112 | + Handle = proxy.XRequest((byte)RequestType.Create, IntPtr.Zero, IntPtr.Zero, 0, 0, IntPtr.Zero, 0, IntPtr.Zero, 0, IntPtr.Zero, 0); |
| 113 | + |
| 114 | + // 将API与队列进行绑定 |
| 115 | + proxy.XRequest((byte)RequestType.Register, Handle, IntPtr.Zero, 0, 0, _Queue.Handle, 0, IntPtr.Zero, 0, IntPtr.Zero, 0); |
| 116 | + |
| 117 | + _Queue.Register(Marshal.GetFunctionPointerForDelegate(_XRespone)); |
| 118 | + // 启动队列循环 |
| 119 | + _Queue.Connect(); |
| 120 | + |
| 121 | + IntPtr ServerIntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ServerInfoField))); |
| 122 | + Marshal.StructureToPtr(Server, ServerIntPtr, false); |
| 123 | + |
| 124 | + IntPtr UserIntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(UserInfoField))); |
| 125 | + Marshal.StructureToPtr(User, UserIntPtr, false); |
| 126 | + |
| 127 | + // 进行连接 |
| 128 | + proxy.XRequest((byte)RequestType.Connect, Handle, IntPtr.Zero, 0, 0, ServerIntPtr, 0, UserIntPtr, 0, Marshal.StringToHGlobalAnsi(Path.GetTempPath()), 0); |
| 129 | + |
| 130 | + Marshal.FreeHGlobal(ServerIntPtr); |
| 131 | + Marshal.FreeHGlobal(UserIntPtr); |
| 132 | + } |
| 133 | + } |
| 134 | + |
| 135 | + public virtual void Disconnect() |
| 136 | + { |
| 137 | + lock(locker) |
| 138 | + { |
| 139 | + IsConnected = false; |
| 140 | + |
| 141 | + if (proxy != null) |
| 142 | + { |
| 143 | + // 将API与队列解绑定 |
| 144 | + proxy.XRequest((byte)RequestType.Register, Handle, IntPtr.Zero, 0, 0, IntPtr.Zero, 0, IntPtr.Zero, 0, IntPtr.Zero, 0); |
| 145 | + proxy.XRequest((byte)RequestType.Release, Handle, IntPtr.Zero, 0, 0, IntPtr.Zero, 0, IntPtr.Zero, 0, IntPtr.Zero, 0); |
| 146 | + |
| 147 | + proxy.Dispose(); |
| 148 | + } |
| 149 | + |
| 150 | + proxy = null; |
| 151 | + Handle = IntPtr.Zero; |
| 152 | + } |
| 153 | + } |
| 154 | + |
| 155 | + private IntPtr _OnRespone(byte type, IntPtr pApi1, IntPtr pApi2, double double1, double double2, IntPtr ptr1, int size1, IntPtr ptr2, int size2, IntPtr ptr3, int size3) |
| 156 | + { |
| 157 | + // 队列过来的消息,如何处理? |
| 158 | + switch((ResponeType)type) |
| 159 | + { |
| 160 | + case ResponeType.OnConnectionStatus: |
| 161 | + _OnConnectionStatus(double1, ptr1,size1); |
| 162 | + break; |
| 163 | + case ResponeType.OnRtnError: |
| 164 | + _OnRtnError(ptr1); |
| 165 | + break; |
| 166 | + default: |
| 167 | + return OnRespone(type, pApi1, pApi2, double1, double2, ptr1, size1, ptr2, size2, ptr3, size3); |
| 168 | + } |
| 169 | + |
| 170 | + return IntPtr.Zero; |
| 171 | + } |
| 172 | + |
| 173 | + protected virtual IntPtr OnRespone(byte type, IntPtr pApi1, IntPtr pApi2, double double1, double double2, IntPtr ptr1, int size1, IntPtr ptr2, int size2, IntPtr ptr3, int size3) |
| 174 | + { |
| 175 | + return IntPtr.Zero; |
| 176 | + } |
| 177 | + |
| 178 | + private void _OnConnectionStatus(double double1, IntPtr ptr1, int size1) |
| 179 | + { |
| 180 | + ConnectionStatus status = (ConnectionStatus)double1; |
| 181 | + // 连接状态更新 |
| 182 | + IsConnected = (ConnectionStatus.Done == status); |
| 183 | + |
| 184 | + RspUserLoginField obj = default(RspUserLoginField); |
| 185 | + |
| 186 | + switch(status) |
| 187 | + { |
| 188 | + case ConnectionStatus.Logined: |
| 189 | + case ConnectionStatus.Disconnected: |
| 190 | + case ConnectionStatus.Doing: |
| 191 | + obj = PInvokeUtility.GetObjectFromIntPtr<RspUserLoginField>(ptr1); |
| 192 | + UserLoginField = obj; |
| 193 | + break; |
| 194 | + default: |
| 195 | + break; |
| 196 | + } |
| 197 | + |
| 198 | + if (OnConnectionStatus != null) |
| 199 | + OnConnectionStatus(this, status, ref obj, size1); |
| 200 | + } |
| 201 | + |
| 202 | + private void _OnRtnError(IntPtr ptr1) |
| 203 | + { |
| 204 | + if (OnRtnError == null) |
| 205 | + return; |
| 206 | + |
| 207 | + ErrorField obj = PInvokeUtility.GetObjectFromIntPtr<ErrorField>(ptr1); |
| 208 | + |
| 209 | + OnRtnError(this, ref obj); |
| 210 | + } |
| 211 | + } |
| 212 | +} |
0 commit comments