public void Test_EndRequest_After_Dispose() { using (TestServer server = new TestServer(ServiceName)) { server.Register(); server.SetData(TopicName, ItemName, 1, Encoding.ASCII.GetBytes(TestData)); using (DdeClient client = new DdeClient(ServiceName, TopicName)) { client.Connect(); IAsyncResult ar = client.BeginRequest(ItemName, 1, null, null); Assert.IsTrue(ar.AsyncWaitHandle.WaitOne(Timeout, false)); client.Dispose(); byte[] data = client.EndRequest(ar); } } }
public async Task<object> GetInvoker(IDictionary<string, object> input) { var services = (IDictionary<string, object>)input["services"]; var callbacks = (IDictionary<string, object>)input["callbacks"]; var encoding = input.ContainsKey("encoding") ? Encoding.GetEncoding((string)input["encoding"]) : null; var decode = encoding == null ? (Func<object, string>)((s) => (string)s) : (s) => HttpUtility.UrlDecode((string)s, encoding); var clients = new List<DdeClient>(); foreach (string service in services.Keys) { var topics = (IDictionary<string, object>)services[service]; foreach (string topic in topics.Keys) { DdeClient client = new DdeClient(decode(service), decode(topic)); clients.Add(client); } } var onDisconnected = (Func<object, Task<object>>)callbacks["OnDisconnected"]; foreach (DdeClient client in clients) { client.Disconnected += async (object sender, DdeDisconnectedEventArgs args) => { var obj = new Dictionary<string, object>(); obj["service"] = client.Service; obj["topic"] = client.Topic; obj["isDisposed"] = args.IsServerInitiated; obj["isServerInitiated"] = args.IsServerInitiated; await Task.Run(async () => await onDisconnected(obj)); }; } var onAdvise = (Func<object, Task<object>>)callbacks["OnAdvise"]; foreach (DdeClient client in clients) { client.Advise += async (object sender, DdeAdviseEventArgs args) => { var obj = new Dictionary<string, object>(); obj["service"] = client.Service; obj["topic"] = client.Topic; obj["item"] = args.Item; obj["text"] = args.Text; await Task.Run(async () => await onAdvise(obj)); }; } return (Func<object, Task<object>>)(async (i) => { var opts = (IDictionary<string, object>)i; var method = (string)opts["method"]; var command = opts.ContainsKey("command") ? (string)opts["command"] : null; var data = opts.ContainsKey("data") ? (string)opts["data"] : null; var format = opts.ContainsKey("format") ? (int)opts["format"] : 1; var timeout = opts.ContainsKey("timeout") ? (int)opts["timeout"] : 10000; var hot = opts.ContainsKey("hot") ? (bool)opts["hot"] : true; var callback = opts.ContainsKey("callback") ? (Func<object, Task<object>>)opts["callback"] : (o) => null; var results = new List<IDictionary<string, object>>(); string item = null; if (opts.ContainsKey("item")) { item = decode((string)opts["item"]); } if (clients.Count == 1 && item != null) // a single client and only one 'item' is supplied. { var client = clients.First(); ((IDictionary<string, object>)services[client.Service])[client.Topic] = new[] { item }; byte[] result = null; switch (method) { case "Request": result = client.Request(item, format, timeout); return Encoding.Default.GetString(result); case "BeginExecute": await Task.Run(() => { var tcs = new TaskCompletionSource<bool>(); AsyncCallback cb = (ar) => { tcs.SetResult(true); }; client.BeginExecute(command, cb, client); var r = tcs.Task.Result; }); break; case "BeginPoke": await Task.Run(() => { var tcs = new TaskCompletionSource<bool>(); AsyncCallback cb = (ar) => { tcs.SetResult(true); }; var bytes = Encoding.Default.GetBytes((string)opts["data"] + "\0"); client.BeginPoke(item, bytes, format, cb, client); var r = tcs.Task.Result; }); break; case "BeginRequest": await Task.Run(() => { var tcs = new TaskCompletionSource<byte[]>(); AsyncCallback cb = (ar) => { tcs.SetResult(client.EndRequest(ar)); }; client.BeginRequest(item, format, cb, client); result = tcs.Task.Result; }); return Encoding.Default.GetString(result); case "BeginStartAdvise": await Task.Run(() => { var tcs = new TaskCompletionSource<bool>(); AsyncCallback cb = (ar) => { tcs.SetResult(true); }; client.BeginStartAdvise(item, format, hot, cb, client); var r = tcs.Task.Result; }); break; case "BeginStopAdvise": await Task.Run(() => { var tcs = new TaskCompletionSource<bool>(); AsyncCallback cb = (ar) => { tcs.SetResult(true); }; client.BeginStopAdvise(item, cb, client); var r = tcs.Task.Result; }); break; case "Service": return client.Service; case "Topic": return client.Topic; case "Handle": return client.Handle; case "IsConnected": return client.IsConnected; case "IsPaused": return client.IsPaused; } } if (clients.Count >= 1) { switch (method) { case "Connect": clients.ForEach((c) => c.Connect()); break; case "Disconnect": clients.ForEach((c) => c.Disconnect()); break; case "Pause": clients.ForEach((c) => c.Pause()); break; case "Resume": clients.ForEach((c) => c.Resume()); break; case "Execute": clients.ForEach((c) => c.Execute(command, timeout)); break; case "Poke": foreach (DdeClient client in clients) { var topics = (IDictionary<string, object>)services[client.Service]; var items = (object[])topics[client.Topic]; foreach (string item_ in items) { client.Poke(decode(item_), data, timeout); } } break; case "Request": foreach (DdeClient client in clients) { var topics = (IDictionary<string, object>)services[client.Service]; var items = ((object[])topics[client.Topic]).Select(decode); foreach (string item_ in items) { var result = client.Request(item_, format, timeout); var obj = new Dictionary<string, object>(); obj["service"] = client.Service; obj["topic"] = client.Topic; obj["item"] = item_; obj["result"] = Encoding.Default.GetString(result); results.Add(obj); } } return results.ToArray(); case "StartAdvise": foreach (DdeClient client in clients) { var topics = (IDictionary<string, object>)services[client.Service]; var items = ((object[])topics[client.Topic]).Select(decode); foreach (string item_ in items) { client.StartAdvise(item_, format, hot, timeout); } } break; case "StopAdvise": foreach (DdeClient client in clients) { var topics = (IDictionary<string, object>)services[client.Service]; var items = ((object[])topics[client.Topic]).Select(decode);; foreach (string item_ in items) { client.StopAdvise(item_, timeout); } } break; case "Dispose": clients.ForEach((c) => c.Dispose()); break; case "Service": return clients.Select((c) => c.Service).ToArray(); case "Topic": return clients.Select((c) => c.Topic).Distinct().ToArray(); case "Handle": return clients.Select((c) => c.Handle).ToArray(); case "IsConnected": return clients.All((c) => c.IsConnected); case "IsPaused": return clients.All((c) => c.IsPaused); } } return null; }); }