簡體   English   中英

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) 中並調用了類 RtdClient.cs。 VS 立即突出顯示以下行:

ComImport, TypeLibType((short)0x1040)
MarshalAs
MethodImpl

並寫入找不到類型和命名空間。

我是否缺少任何參考資料? 我添加了對 COM 類型 Tos.RTD 的引用,但沒有幫助。

同樣在注冊表中,我找到了帶有 Tos.RTD 和 CLSID 的文件夾。 我假設 CSLID 指向 COM 類型?

在 VS Tos.RTD 中有幾個接口。 在上面的鏈接中,我沒有看到這些接口的方法的實現。 怎么了?

我還通過反射閱讀了以下RTD我知道第二個鏈接依賴於反射。 這兩種方法的優點/缺點是什么? 哪一個在概念上更有意義?

正如你所看到的那樣,我迷路了,所以任何建議將不勝感激。

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 http://stackoverflow.com/questions/26726430/r6025-pure-virtual-function-call


            //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();

        }


    }
}

RTD 服務器明確用於 Excel,不會在 C# 中為您提供幫助。 我想你可以反編譯它,看看它是如何從 ThinkOrSwim 獲取數據的,但我想他們有一個 API,如果你環顧四周,你已經可以使用它了。

我在上面找到了 Silvo's Answer 的 Git 存儲庫。 最近好像更新了。

在這里找到: https : //github.com/neberej/tos-client

上面的代碼可以在“Adapter”文件夾中找到。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM