R6025纯虚函数调用 [英] R6025 pure virtual function call

查看:260
本文介绍了R6025纯虚函数调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我收到随机R6025 - 使用ThinkOrSwim这个定制的C#RTD客户端时,在随机时间纯虚函数调用错误。



我怎么能一)进行调试,找出什么错误,和b)解决它?



在窗口弹出消息框,说有一个错误,代码保持在研究背景运行,没有异常抛出。但是当我点击消息中的确定,Windows关闭应用程序下来



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

  VAR tosClassId =新的GUID(Registry.GetValue(@HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Tos.RTD\CLSID,,NULL)的ToString()); 
变种rtdClient =新RtdClient(tosClassId);

VAR日期= DateTime.Now.Date;
的foreach(在futureSymbols VAR futureSymbol){
VAR结算= GetDouble(rtdClient,futureSymbol,CLOSE);
收益回报新TOSEODDataPoint {
日期=日期,
结算=结算,
};
}

静态双GetDouble(IRtdClient客户端,串符号,串题){
对象的值;
如果(client.GetValue(TimeSpan.FromSeconds(3),超时值,主题,符号)){
尝试{返回double.Parse(value.ToString()); } {赶上返回0; }
}
返回0;
}

下面是RTD客户端实现:

  //由http://awkwardcoder.com/2014/01/24/excel-rtd-client-in-c/ 
$ b $启发b酒店的公共接口IRtdClient {
BOOL的GetValue(时间跨度超时,出对象的值,params对象[]参数);
}

公共类RtdClient:IRtdClient {

只读的Guid SERVERID;
静态只读字典< GUID,请IRtdServer>服务器=新词典< GUID,请IRtdServer>();
静态只读字典< GUID,请INT> topicIds =新词典< GUID,请INT>();

公共RtdClient(GUID SERVERID){
SERVERID =服务器ID;
}

公共BOOL的GetValue(时间跨度超时,出对象的值,params对象[]参数){

值= NULL;
VAR服务器= GetRtdServer();
VAR topicId = GetTopicId();

变种SW = Stopwatch.StartNew();

尝试{
server.ConnectData(topicId,ARGS,真正的);
,而(sw.Elapsed<超时){
VAR活着= server.Heartbeat();
如果(活着= 1!){
// TODO:这里应该做些什么?
返回FALSE;
}
变种刷新= server.RefreshData(1);
如果(refresh.Length大于0){
如果(刷新[0,0]的ToString()== topicId.ToString()){
值为=刷新[1,0 ];
返回真;
}
}
Thread.sleep代码(20);
}
}赶上(例外前){
// TODO:登录异常
返回FALSE;
} {最后
server.DisconnectData(topicId);
sw.Stop();
}
返回FALSE;
}

IRtdServer GetRtdServer(){
IRtdServer服务器;
如果(servers.TryGetValue(SERVERID,出服务器)!){
型RTD = Type.GetTypeFromCLSID(服务器ID);
服务器=(IRtdServer)Activator.CreateInstance(RTD);
服务器[SERVERID] =服务器;
}
返回服务器;
}

INT GetTopicId(){
INT topicId = 0;
如果(topicIds.TryGetValue(SERVERID,出topicId)){
topicId ++;
}
topicIds [SERVERID] = topicId;
返回topicId;
}
}

[ComImport,TypeLibType((短)0x1040)的Guid(EC0E6191-DB51-11D3-8F3E-00C04F3651B8)]
公共接口IRtdServer {
[MethodImpl(MethodImplOptions.InternalCall,MethodCodeType = MethodCodeType.Runtime),DISPID(10)]
INT ServerStart([在,的MarshalAs(UnmanagedType.Interface)] IRTDUpdateEvent回调);

[返回:的MarshalAs(UnmanagedType.Struct)
[MethodImpl(MethodImplOptions.InternalCall,MethodCodeType = MethodCodeType.Runtime),DISPID(11)]
对象CONNECTDATA([在]诠释topicId,[在,的MarshalAs(UnmanagedType.SafeArray,SafeArraySubType = VarEnum.VT_VARIANT)Ref对象[]参数,[输入,输出]参考布尔为newValue);

[返回:的MarshalAs(UnmanagedType.SafeArray,SafeArraySubType = VarEnum.VT_VARIANT)]
[MethodImpl(MethodImplOptions.InternalCall,MethodCodeType = MethodCodeType.Runtime),DISPID(12)] $ B $对象b [,] RefreshData([输入,输出]参考INT topicCount);

[MethodImpl(MethodImplOptions.InternalCall,MethodCodeType = MethodCodeType.Runtime),DISPID(13)]
空隙DisconnectData([IN] INT topicId);

[MethodImpl(MethodImplOptions.InternalCall,MethodCodeType = MethodCodeType.Runtime),DISPID(14)]
INT心跳();

[MethodImpl(MethodImplOptions.InternalCall,MethodCodeType = MethodCodeType.Runtime),DISPID(15)]
空隙ServerTerminate();
}

[ComImport,TypeLibType((短)0x1040)的Guid(A43788C1-D91B-11D3-8F39-00C04F3651B8)]
公共接口IRTDUpdateEvent {
〔MethodImpl(MethodImplOptions.InternalCall,MethodCodeType = MethodCodeType.Runtime),DISPID(10),PreserveSig]
空隙UpdateNotify();

[DISPID(11)]
INT HeartbeatInterval {
[MethodImpl(MethodImplOptions.InternalCall,MethodCodeType = MethodCodeType.Runtime),DISPID(11)]
的get;
[参数:在]
[MethodImpl(MethodImplOptions.InternalCall,MethodCodeType = MethodCodeType.Runtime),DISPID(11)]
组;
}

[MethodImpl(MethodImplOptions.InternalCall,MethodCodeType = MethodCodeType.Runtime),DISPID(12)]
无效断开();
}


解决方案

下面就是我固定通过使失败较少的问题...现在有200ms的初始延迟和延迟加倍循环的每次迭代。 (现在还在寻找一个真正的解决方案)

 公共BOOL的GetValue(时间跨度超时,出对象的值,params对象[]参数) {

值= NULL;
VAR服务器= GetRtdServer();
VAR topicId = GetTopicId();

变种SW = Stopwatch.StartNew();
VAR延迟= 200;

尝试{
server.ConnectData(topicId,ARGS,真正的);
,而(sw.Elapsed<超时){
Thread.sleep代码(延迟);
延迟* = 2;
VAR活着= server.Heartbeat();
如果(活着= 1!){
// TODO:这里应该做些什么?
返回FALSE;
}
变种刷新= server.RefreshData(1);
如果(refresh.Length大于0){
如果(刷新[0,0]的ToString()== topicId.ToString()){
值为=刷新[1,0 ];
返回真;
}
}
}
}赶上(例外前){
// TODO:登录异常
返回FALSE;
} {最后
server.DisconnectData(topicId);
sw.Stop();
}
返回FALSE;
}


I am getting random R6025 - pure virtual function call errors at random times when using this custom c# RTD client for ThinkOrSwim.

How can I a) debug it to find out what's going wrong, and b) fix it?

When windows pops up the message box saying there is an error, the code keeps running in the backgroud and no exceptions are thrown. But when I click OK on the message box, windows shuts the application down.

Here is a snippet of the code requesting RTD data:

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;
}

Here is the RTD client implementation:

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

解决方案

Here's how I "fixed" the issue by making it fail less often ... there is now an initial delay of 200ms and the delay doubles every iteration of the loop. (Am still looking for a real solution)

    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;
    }

这篇关于R6025纯虚函数调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆