2014-11-04 8 views
0

Я получаю случайный R6025 - чистые ошибки вызова виртуальной функции в случайные моменты времени при использовании этого пользовательского клиента C# RTD для ThinkOrSwim.вызов виртуальной функции R6025

Как я могу отладить его, чтобы узнать, что происходит не так, и б) исправить его?

Когда окна всплывают в окне сообщения о том, что есть ошибка, код продолжает работать в backgroud и никаких исключений не выбрасывается. Но когда я нажимаю OK в окне сообщения, окна закрывают приложение.

Вот фрагмент кода запроса 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

Произошла ли ошибка во время вызова на сервер? –

+0

Привет, Бен :) Я не могу отлаживать, чтобы выяснить, что именно ускоряет ошибку. Я предполагаю, что это где-то в методе GetValue – bboyle1234

+0

Я имею в виду, я не могу отлаживать, потому что ошибка R6025 не прерывает код C#, который продолжает работать, пока я не нажму OK в окне окна windows – bboyle1234

ответ

0

Вот как я «фиксированный» вопрос, сделав его не в состоянии реже ... теперь начальная задержка составляет 200 мс, а задержка удваивает каждую итерацию цикла. (Я все еще ищу реальное решение)

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