2014-11-04 123 views
0

当随机时使用此自定义c#RTD客户端用于ThinkOrSwim时,我随机得到R6025 - 纯虚函数调用错误。R6025纯虚函数调用

我怎样才能a)调试它,找出哪里出了问题,并b)修复它?

当窗口弹出消息框指出存在错误时,代码将继续在背景中运行,并且不会引发异常。但是当我在消息框上单击确定时,Windows会关闭应用程序。

下面是代码的请求RTD数据片段:

var tosClassId = new Guid(Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Tos.RTD\CLSID", "", null).ToString()); 
var rtdClient = new RtdClient(tosClassId); 

var date = DateTime.Now.Date; 
foreach (var futureSymbol in futureSymbols) { 
    var settlement = GetDouble(rtdClient, futureSymbol, "CLOSE"); 
    yield return new TOSEODDataPoint { 
     Date = date, 
     Settlement = settlement, 
    }; 
} 

static double GetDouble(IRtdClient client, string symbol, string topic) { 
    object value; 
    if (client.GetValue(TimeSpan.FromSeconds(3), out value, topic, symbol)) { 
     try { return double.Parse(value.ToString()); } catch { return 0; } 
    } 
    return 0; 
} 

这里是RTD客户端实现:

// Inspired by http://awkwardcoder.com/2014/01/24/excel-rtd-client-in-c/ 

public interface IRtdClient { 
    bool GetValue(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 GetValue(TimeSpan timeout, out object value, params object[] args) { 

     value = null; 
     var server = GetRtdServer(); 
     var topicId = GetTopicId(); 

     var sw = Stopwatch.StartNew(); 

     try { 
      server.ConnectData(topicId, args, true); 
      while (sw.Elapsed < timeout) { 
       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; 
        } 
       } 
       Thread.Sleep(20); 
      } 
     } 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(); 
} 
+0

在调用服务器期间发生错误? – 2014-11-04 02:11:02

+0

嗨本:)我无法调试,以弄清楚究竟是什么促成了错误。我认为它在GetValue方法 – bboyle1234 2014-11-04 02:17:54

+0

中的某处我的意思是,我无法调试,因为R6025错误不会中断C#代码,该代码会一直运行,直到我在Windows消息框中单击确定 – bboyle1234 2014-11-04 02:18:44

回答

0

这里是我如何使它失败次数减少“固定”的问题...现在有一个200ms的初始延迟,并且该延迟在循环的每次迭代中都会增加一倍。 (我仍在寻找真正的解决方案)

public bool GetValue(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; 
    }