C# 中的 RTD 服务器 - 从哪里开始
RTD server in C# - where to start
我在 Excel 中有 RTD 服务器,它从 thinkorswim 应用程序中提取数据。我想改为将数据拉入 C#。我的编程经验有限,因此阅读了多篇有关 C# 中 RTD 服务器实现的教程,但其中大部分对我来说都是两个高级教程。所以我想知道是否有人可以推荐一些介绍性的阅读材料。这是我要实现的示例代码:
http://awkwardcoder.com/2014/01/24/excel-rtd-client-in-c/
我把它复制粘贴到Visual Studio(VS)里,调用了classRtdClient.cs。 VS 立即突出显示以下行:
ComImport, TypeLibType((short)0x1040)
MarshalAs
MethodImpl
并找不到写入的类型和命名空间。
我是否遗漏了任何参考资料?
我添加了对 COM 类型的引用 Tos.RTD,但没有帮助。
我还在注册表中找到了带有 Tos.RTD 和 CLSID 的文件夹。我假设 CSLID 指向 COM 类型?
在 VS 中 Tos.RTD 有几个接口。在上面link中,我没有看到这些接口方法的实现。怎么了?
我还阅读了以下内容 RTD through reflection 我了解第二个 link 依赖于反思。两种方法的 benefits/drawbacks 是什么?哪一个在概念上更有意义?
正如你所见,我迷路了,所以任何建议将不胜感激。
RTD 服务器明确适用于 Excel,不会在 C# 中为您提供帮助。我想你可以反编译它,看看它是如何从 ThinkOrSwim 获取数据的,但我想他们有一个 API 如果你多看看,你已经可以使用了。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
namespace MyRTD
{
class Program
{
static void Main(string[] args)
{
//Based off of http://awkwardcoder.com/2014/01/24/excel-rtd-client-in-c/
//and
//var tosClassId = new Guid(Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Tos.RTD\CLSID", "", null).ToString());
var tosClassId=new Guid("{1B415BA9-E543-41BD-8EB1-CB12A5B7678F}");
var rtdClient = new RtdClient(tosClassId);
var date = DateTime.Now.Date;
List<string> tos_sym = new List<string>();
tos_sym.Add(".AAPL160819C106");
tos_sym.Add(".AAPL160819C107");
tos_sym.Add(".AAPL160819C108");
tos_sym.Add(".AAPL160819C109");
foreach (var optSym in tos_sym)
{
var optBid = GetDouble(rtdClient, optSym, "BID");
var optAsk = GetDouble(rtdClient, optSym, "ASK");
var optDelt = GetDouble(rtdClient, optSym, "DELTA");
Console.WriteLine(optSym + " BID: " + optBid + " ASK: " + optAsk + " DELTA: " + optDelt);
}
}
static double GetDouble(IRtdClient client, string symbol, string topic) {
object value;
if (client.GetValue2(TimeSpan.FromSeconds(3), out value, topic, symbol)) {
try { return double.Parse(value.ToString()); } catch { return 0; }
}
return 0;
}
public interface IRtdClient
{
bool GetValue2(TimeSpan timeout, out object value, params object[] args);
}
public class RtdClient : IRtdClient
{
readonly Guid ServerId;
static readonly Dictionary<Guid, IRtdServer> servers = new Dictionary<Guid, IRtdServer>();
static readonly Dictionary<Guid, int> topicIds = new Dictionary<Guid, int>();
public RtdClient(Guid serverId)
{
ServerId = serverId;
}
public bool GetValue2(TimeSpan timeout, out object value, params object[] args)
{
value = null;
var server = GetRtdServer();
var topicId = GetTopicId();
var sw = Stopwatch.StartNew();
var delay = 200;
try
{
server.ConnectData(topicId, args, true);
while (sw.Elapsed < timeout)
{
Thread.Sleep(delay);
delay *= 2;
var alive = server.Heartbeat();
if (alive != 1)
{
// TODO: What should be done here?
return false;
}
var refresh = server.RefreshData(1);
if (refresh.Length > 0)
{
if (refresh[0, 0].ToString() == topicId.ToString())
{
value = refresh[1, 0];
return true;
}
}
}
}
catch (Exception ex)
{
// TODO: Log exception
return false;
}
finally
{
server.DisconnectData(topicId);
sw.Stop();
}
return false;
}
IRtdServer GetRtdServer()
{
IRtdServer server;
if (!servers.TryGetValue(ServerId, out server))
{
Type rtd = Type.GetTypeFromCLSID(ServerId);
server = (IRtdServer)Activator.CreateInstance(rtd);
servers[ServerId] = server;
}
return server;
}
int GetTopicId()
{
int topicId = 0;
if (topicIds.TryGetValue(ServerId, out topicId))
{
topicId++;
}
topicIds[ServerId] = topicId;
return topicId;
}
}
[ComImport, TypeLibType((short)0x1040), Guid("EC0E6191-DB51-11D3-8F3E-00C04F3651B8")]
public interface IRtdServer
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(10)]
int ServerStart([In, MarshalAs(UnmanagedType.Interface)] IRTDUpdateEvent callback);
[return: MarshalAs(UnmanagedType.Struct)]
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(11)]
object ConnectData([In] int topicId, [In, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] ref object[] parameters, [In, Out] ref bool newValue);
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)]
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(12)]
object[,] RefreshData([In, Out] ref int topicCount);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(13)]
void DisconnectData([In] int topicId);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(14)]
int Heartbeat();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(15)]
void ServerTerminate();
}
[ComImport, TypeLibType((short)0x1040), Guid("A43788C1-D91B-11D3-8F39-00C04F3651B8")]
public interface IRTDUpdateEvent
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(10), PreserveSig]
void UpdateNotify();
[DispId(11)]
int HeartbeatInterval
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(11)]
get;
[param: In]
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(11)]
set;
}
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(12)]
void Disconnect();
}
}
}
我在上面找到了 Silvo 的回答的 Git 回购协议。
好像最近更新了。
在此处找到:https://github.com/neberej/tos-client
上面的代码可以在“适配器”文件夹中找到。
我在 Excel 中有 RTD 服务器,它从 thinkorswim 应用程序中提取数据。我想改为将数据拉入 C#。我的编程经验有限,因此阅读了多篇有关 C# 中 RTD 服务器实现的教程,但其中大部分对我来说都是两个高级教程。所以我想知道是否有人可以推荐一些介绍性的阅读材料。这是我要实现的示例代码:
http://awkwardcoder.com/2014/01/24/excel-rtd-client-in-c/
我把它复制粘贴到Visual Studio(VS)里,调用了classRtdClient.cs。 VS 立即突出显示以下行:
ComImport, TypeLibType((short)0x1040)
MarshalAs
MethodImpl
并找不到写入的类型和命名空间。
我是否遗漏了任何参考资料? 我添加了对 COM 类型的引用 Tos.RTD,但没有帮助。
我还在注册表中找到了带有 Tos.RTD 和 CLSID 的文件夹。我假设 CSLID 指向 COM 类型?
在 VS 中 Tos.RTD 有几个接口。在上面link中,我没有看到这些接口方法的实现。怎么了?
我还阅读了以下内容 RTD through reflection 我了解第二个 link 依赖于反思。两种方法的 benefits/drawbacks 是什么?哪一个在概念上更有意义?
正如你所见,我迷路了,所以任何建议将不胜感激。
RTD 服务器明确适用于 Excel,不会在 C# 中为您提供帮助。我想你可以反编译它,看看它是如何从 ThinkOrSwim 获取数据的,但我想他们有一个 API 如果你多看看,你已经可以使用了。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
namespace MyRTD
{
class Program
{
static void Main(string[] args)
{
//Based off of http://awkwardcoder.com/2014/01/24/excel-rtd-client-in-c/
//and
//var tosClassId = new Guid(Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Tos.RTD\CLSID", "", null).ToString());
var tosClassId=new Guid("{1B415BA9-E543-41BD-8EB1-CB12A5B7678F}");
var rtdClient = new RtdClient(tosClassId);
var date = DateTime.Now.Date;
List<string> tos_sym = new List<string>();
tos_sym.Add(".AAPL160819C106");
tos_sym.Add(".AAPL160819C107");
tos_sym.Add(".AAPL160819C108");
tos_sym.Add(".AAPL160819C109");
foreach (var optSym in tos_sym)
{
var optBid = GetDouble(rtdClient, optSym, "BID");
var optAsk = GetDouble(rtdClient, optSym, "ASK");
var optDelt = GetDouble(rtdClient, optSym, "DELTA");
Console.WriteLine(optSym + " BID: " + optBid + " ASK: " + optAsk + " DELTA: " + optDelt);
}
}
static double GetDouble(IRtdClient client, string symbol, string topic) {
object value;
if (client.GetValue2(TimeSpan.FromSeconds(3), out value, topic, symbol)) {
try { return double.Parse(value.ToString()); } catch { return 0; }
}
return 0;
}
public interface IRtdClient
{
bool GetValue2(TimeSpan timeout, out object value, params object[] args);
}
public class RtdClient : IRtdClient
{
readonly Guid ServerId;
static readonly Dictionary<Guid, IRtdServer> servers = new Dictionary<Guid, IRtdServer>();
static readonly Dictionary<Guid, int> topicIds = new Dictionary<Guid, int>();
public RtdClient(Guid serverId)
{
ServerId = serverId;
}
public bool GetValue2(TimeSpan timeout, out object value, params object[] args)
{
value = null;
var server = GetRtdServer();
var topicId = GetTopicId();
var sw = Stopwatch.StartNew();
var delay = 200;
try
{
server.ConnectData(topicId, args, true);
while (sw.Elapsed < timeout)
{
Thread.Sleep(delay);
delay *= 2;
var alive = server.Heartbeat();
if (alive != 1)
{
// TODO: What should be done here?
return false;
}
var refresh = server.RefreshData(1);
if (refresh.Length > 0)
{
if (refresh[0, 0].ToString() == topicId.ToString())
{
value = refresh[1, 0];
return true;
}
}
}
}
catch (Exception ex)
{
// TODO: Log exception
return false;
}
finally
{
server.DisconnectData(topicId);
sw.Stop();
}
return false;
}
IRtdServer GetRtdServer()
{
IRtdServer server;
if (!servers.TryGetValue(ServerId, out server))
{
Type rtd = Type.GetTypeFromCLSID(ServerId);
server = (IRtdServer)Activator.CreateInstance(rtd);
servers[ServerId] = server;
}
return server;
}
int GetTopicId()
{
int topicId = 0;
if (topicIds.TryGetValue(ServerId, out topicId))
{
topicId++;
}
topicIds[ServerId] = topicId;
return topicId;
}
}
[ComImport, TypeLibType((short)0x1040), Guid("EC0E6191-DB51-11D3-8F3E-00C04F3651B8")]
public interface IRtdServer
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(10)]
int ServerStart([In, MarshalAs(UnmanagedType.Interface)] IRTDUpdateEvent callback);
[return: MarshalAs(UnmanagedType.Struct)]
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(11)]
object ConnectData([In] int topicId, [In, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] ref object[] parameters, [In, Out] ref bool newValue);
[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)]
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(12)]
object[,] RefreshData([In, Out] ref int topicCount);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(13)]
void DisconnectData([In] int topicId);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(14)]
int Heartbeat();
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(15)]
void ServerTerminate();
}
[ComImport, TypeLibType((short)0x1040), Guid("A43788C1-D91B-11D3-8F39-00C04F3651B8")]
public interface IRTDUpdateEvent
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(10), PreserveSig]
void UpdateNotify();
[DispId(11)]
int HeartbeatInterval
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(11)]
get;
[param: In]
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(11)]
set;
}
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(12)]
void Disconnect();
}
}
}
我在上面找到了 Silvo 的回答的 Git 回购协议。 好像最近更新了。
在此处找到:https://github.com/neberej/tos-client
上面的代码可以在“适配器”文件夹中找到。