I am trying to access the API using ThomsonReuters.Desktop.SDK, I have the example client. When I am get data I get the following error, any idea why ? :
Hi
I ended up solving like this:
private void Start()
{
var wh = new ManualResetEvent(false);
this._thread = new Thread(() =>
Services = DataServices.Instance;
Services.Initialize("GKAPIv2");
Services.StateChanged += ServicesOnStateChanged;
this._realTime = DataServices.Instance.Realtime;
System.Windows.Threading.Dispatcher.Run();
wh.Set();
Dispatcher.PushFrame(Frame);
});
this._thread.Start();
if (wh.WaitOne(5000))
throw new Exception("Failed to initialize API");
}
this._isRunning = true;
Thanks for your help guys.
Best
Gordon
@gordon.konheiser
You may use the Dependencies tool to verify the problem. This tool will verify the dependencies of the DLL file.
I can run the application properly with .NET Framework 4.5.1. Then, I checked the dependencies of the ThomsonReuters.Desktop.SDK.DataAccess.dll and found that it loads Systems.Configuration.dll from C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Configuration\v4.0_4.0.0.0__b03f5f7f11d50a3a.
What is the version of the .NET Framework that you are using?
Please also share the content in the packages.config file.
<?xml version="1.0" encoding="utf-8"?><packages> <package id="Common.Logging" version="2.1.2" targetFramework="net451" /> <package id="Newtonsoft.Json" version="6.0.8" targetFramework="net451" /> <package id="protobuf-net" version="2.0.0.668" targetFramework="net451" /> <package id="ThomsonReuters.Desktop.SDK.DataAccess.Signed" version="1.8.4" targetFramework="net451" /> <package id="ThomsonReuters.Udap.Ipc.Signed" version="2.10.5" targetFramework="net451" /></packages>
I am targeting .NET Core 3.1
I copied the packages.config over from the DataApiExampleRealtimeData app :
And this is the full error I get:
Error:
ThomsonReuters.Desktop.SDK.DataAccess.TinyIoCResolutionException : Unable to resolve type: ThomsonReuters.Desktop.SDK.DataAccess.IInternalDataServices
---- ThomsonReuters.Desktop.SDK.DataAccess.TinyIoCResolutionException : Unable to resolve type: ThomsonReuters.Desktop.SDK.DataAccess.IInternalDataServices
-------- ThomsonReuters.Desktop.SDK.DataAccess.TinyIoCResolutionException : Unable to resolve type: ThomsonReuters.Desktop.SDK.DataAccess.UdapService
------------ ThomsonReuters.Desktop.SDK.DataAccess.TinyIoCResolutionException : Unable to resolve type: ThomsonReuters.Desktop.SDK.DataAccess.Connection
---------------- ThomsonReuters.Desktop.SDK.DataAccess.TinyIoCResolutionException : Unable to resolve type: ThomsonReuters.Udap.Ipc.Managed.Common.BusAdapter.IEikonBus
-------------------- System.TypeInitializationException : The type initializer for 'ThomsonReuters.Udap.Ipc.Managed.Common.BusAdapter.EikonBus' threw an exception.
------------------------ Common.Logging.ConfigurationException : Failed obtaining configuration for Common.Logging from configuration section 'common/logging'.
---------------------------- System.IO.FileNotFoundException : Could not load file or assembly 'System.Configuration.ConfigurationManager, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified.
at ThomsonReuters.Desktop.SDK.DataAccess.TinyIoCContainer.DelegateFactory.GetObject(Type requestedType, TinyIoCContainer container, NamedParameterOverloads parameters, ResolveOptions options)
at ThomsonReuters.Desktop.SDK.DataAccess.TinyIoCContainer.ResolveInternal(TypeRegistration registration, NamedParameterOverloads parameters, ResolveOptions options)
at ThomsonReuters.Desktop.SDK.DataAccess.TinyIoCContainer.Resolve(Type resolveType, String name)
at ThomsonReuters.Desktop.SDK.DataAccess.TinyIoCContainer.Resolve[ResolveType](String name)
at ThomsonReuters.Desktop.SDK.DataAccess.DataServices.get_Instance()
at ReutersAPIv1.Classes.ReutersApi.GetData(String reutersRic, String field) in C:\Dev\ReutersApiV1\ReutersAPIv1\Classes\ReutersApi.cs:line 27
at ReutersAPIv1Tests.IntegrationTests.GetDataTest() in C:\Dev\ReutersApiV1\ReutersAPIv1Tests\IntegrationTests.cs:line 31
----- Inner Stack Trace -----
at ThomsonReuters.Desktop.SDK.DataAccess.Bootstrapper.<>c__DisplayClass21.<Initialize>b__11(IIocContainer a, NamedParameterOverloads b)
at ThomsonReuters.Desktop.SDK.DataAccess.TinyIoCContainer.ConstructType(Type requestedType, Type implementationType, ConstructorInfo constructor, NamedParameterOverloads parameters, ResolveOptions options)
at ThomsonReuters.Desktop.SDK.DataAccess.TinyIoCContainer.ConstructType(Type requestedType, Type implementationType, ConstructorInfo constructor, ResolveOptions options)
at ThomsonReuters.Desktop.SDK.DataAccess.TinyIoCContainer.SingletonFactory.GetObject(Type requestedType, TinyIoCContainer container, NamedParameterOverloads parameters, ResolveOptions options)
at ThomsonReuters.Desktop.SDK.DataAccess.TinyIoCContainer.Resolve(Type resolveType)
at ThomsonReuters.Desktop.SDK.DataAccess.TinyIoCContainer.Resolve[ResolveType]()
at ThomsonReuters.Desktop.SDK.DataAccess.Bootstrapper.<Initialize>b__10(IIocContainer a, NamedParameterOverloads b)
at ThomsonReuters.Desktop.SDK.DataAccess.Bootstrapper.<>c__DisplayClass21.<Initialize>b__1(IIocContainer a, NamedParameterOverloads b)
at Common.Logging.Configuration.ArgUtils.Guard[T](Function`1 function, String messageFormat, Object[] args)
at Common.Logging.Configuration.ArgUtils.Guard(Action action, String messageFormat, Object[] args)
at Common.Logging.LogManager.BuildLoggerFactoryAdapter()
at Common.Logging.LogManager.get_Adapter()
at Common.Logging.LogManager.GetCurrentClassLogger()
at ThomsonReuters.Udap.Ipc.Managed.Common.BusAdapter.EikonBus..cctor()
at Common.Logging.Configuration.DefaultConfigurationReader.GetSection(String sectionName)
at Common.Logging.LogManager.<>c__DisplayClass6.<BuildLoggerFactoryAdapter>b__3()
at Common.Logging.Configuration.ArgUtils.<>c__DisplayClass13.<Guard>b__12()
I don't think that it supports .NET Core.
I got this error when targeting .NET core.
Package 'ThomsonReuters.Desktop.SDK.DataAccess.Signed 1.8.4' was restored using '.NETFramework,Version=v4.6.1, .NETFramework,Version=v4.6.2, .NETFramework,Version=v4.7, .NETFramework,Version=v4.7.1, .NETFramework,Version=v4.7.2, .NETFramework,Version=v4.8' instead of the project target framework '.NETCoreApp,Version=v3.1'. This package may not be fully compatible with your project.
I created a new project using .Net Framework 4.5 and haev the same problem
It is looking fir a file but no idea what
FileNotFoundException: Could not load file or assembly 'System.Configuration.ConfigurationManager, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified.
How did you install the ThomsonReuters.Desktop.SDK.DataAccess package?
Have you installed it via NuGet?
Everything works fine when I create a new project and then install the package via NuGet.
I installed form nuget
new project
Is there any update to my problem ?
Thank you for the log file.
I verified the log file and found that it didn't locate or load any ThomsonReuters.Desktop.SDK or System.Configuration libraries. It seems that the application stopped before loading those libraries.
You may use Fuslogvw.exe to displays details for assembly binds. Run it in the Developer Command Prompt for Visual Studio with administrator credentials. Then select Settings... to enable logging and log path.
After that replicate the issue. In the log path, you will see the Default\<process name> folder. You may enable "Log bind failures to disk" to only see the failures.
Otherwise, you can share your project files so I can try to run it on my machine.
Morning,
So yesterday I scraped the project and started again. Now everything builds and I am able to sent requests but Im not getting a response. Ive checked the ric and field and that looks good. Any ideas ?
I will send you the project files
I have run the code, as follows.
class Program { static void Main(string[] args) { var t = typeof(ReutersFields); var conts = t.GetFields(); var x = conts[0].Name; var wh = new ManualResetEvent(false); var reutersApi = new ReutersApi(); var field = ReutersFields.NextReleaseDate; var ric = ReutersRics.EIAWeeklyGasRelease; reutersApi.Reply += delegate (object sender, ReutersApiReplyEventArgs args1) { Console.WriteLine($"{args1.Value.Field}: {args1.Value.RawValue.ToString()}"); //wh.Set(); }; reutersApi.GetData(ric, field); reutersApi.ServiceStateChange += delegate (object sender, DataServicesStateChangedEventArgs args1) { Console.WriteLine(args1.State.ToString()); }; System.Windows.Forms.Application.Run(); } }
I can retrieve the data properly.
Hi,
Great you are able to execute the code, I still get nothing back, even when I run your code , any ideas ?
Thanks
Morning, I am still unable to get a response back. Do I need to register the app name anywhere , what else could the problem be ?
No, you don't need to register the app name. If an example you downloaded from Refinitiv Developer Portal works for you, and the application you created does not, it suggests the issue is with your code. Are you saying you don't see any events raised by Eikon .NET SDK? If this is the case, the most likely reason I can think of is that Windows Message Pump is not running on the thread housing Eikon .NET SDK assemblies. Eikon .NET SDK requires that Windows Message Pump is running on the thread housing Eikon .NET SDK assemblies. Otherwise Eikon .NET SDK cannot raise events. In a GUI application Windows Message Pump is automatically started on the GUI thread. In a Console application you need to explicitly kick off Windows Message Pump. One way to kick off Windows Message Pump is by using Application.Run method of Windows Forms. Another way is by pushing Dispatcher frames (this method is used in the examples on this portal).
Hi Alex, Thank you very much it was indeed the Dispatcher.
So I am now getting replies. the problme I am trying to solve now is how would I reset/ release the dispatcher to allow for a new request using the same RealTimeService, i hope you know what I mean.
So at the moment i call the API like this:
And when I get my reply I am doing this:
But I get nothing back from the second call ?
Is there a reason why you discontinue the Dispatcher frame? I'm not quite sure what you're looking to achieve with this. Unless you have a specific reason for discontinuing the Dispatcher frame, you could keep it running for as long as you need Eikon .NET SDK assemblies o retrieve data from Eikon. This is not to say that you must keep it running. The question you're asking is potentially quite loaded. The bottom line is that you need to ensure Windows Message Pump is running on the thread housing Eikon .NET SDK assemblies as long as you need those assemblies to retrieve data from Eikon. The simplest way to achieve this is to use Application.Run method of Windows Forms. At the same time there is quite a number of potential considerations here, hence it's practically impossible to give one recommendation that would be applicable to all possible use cases.
I just want to be able to make multiple requests at the moment the Dispatcher.PushFrame(Frame); is blocking any further requests. I am not using windows forms, it there not an easy way to achieve this ?
And you cant start Dispatcher.PushFrame in another thread;
First I need to say that we very strongly recommend that all data retrieval using Eikon .NET SDK is done on a single thread. As I said earlier, the easiest way to ensure Windows Message Pump is running is indeed to use Windows Forms. This does not mean you need to turn your console application into a GUI application. You just need to include Windows Forms assembly in your project and call System.Windows.Forms.Application.Run() on the thread housing Eikon .NET SDK. See an example in the post from 11 Nov 2020 by @Jirapongse on this thread on the forum. Alternatively you could keep the Dispatcher frame running (simply don't discontinue it explicitly by setting Frame.Continue=false). These two options would be the easiest. But like I said, there's no one recommendation that could be applicable to all possible use cases here. If you're not happy with one of the above options, then we need to go to a much deeper level of detail about your application. Then you need to explain the structure of your application, the constraints you're working within and provide detailed explanation for your objections to the above options. Only then we can think what alternatives (if any) may be preferable for your specific use case.
I must be missing something because when you run Dispatcher.PushFrame(Frame) it blocks the thread you are running on, so I dont see how it can be single threaded ? I get the first request back but then the code is stuck in the Frame loop, if that makes sense ? Would it be possible to have a quick call ?
I'm afraid this makes little sense to me. I don't see how Dispatcher.PushFrame(Frame) blocks the thread. It ensures that the thread is running and does not terminate, which is what you want as long as you want to retrieve data, right? But it does not block the thread. At what point does the thread get blocked for you? And how do you experience it? On my end I have no problem making multiple data requests after executing Dispatcher.PushFrame(Frame) on the thread housing Eikon .NET SDK assemblies. I can send multiple requests simultaneously or I can send them sequentially scheduling the next request after the data for the previous one has been retrieved. Here's a code snippet modifying TimeSeriesRequestExample class in UsageExample.cs module in the usage example for timeseries data downloaded from Eikon .NET SDK page on this portal. With this modification the console application requests timeseries for EUR=, and then after the timeseries for EUR= are fully retrieved it requests timeseries for GBP=. All of this works, which means the thread is not blocked at any point.
public class TimeSeriesRequestExample { private readonly ITimeSeriesDataService timeSeries; private ITimeSeriesDataRequest request; public TimeSeriesRequestExample(ITimeSeriesDataService timeSeries) { this.timeSeries = timeSeries; } public void Launch() { RequestTimeseries("EUR="); } private void RequestTimeseries(string ric) { request = timeSeries.SetupDataRequest(ric) .WithInterval(CommonInterval.Daily) .WithNumberOfPoints(10) .OnDataReceived(DataReceivedCallback) .CreateAndSend(); } private void DataReceivedCallback(DataChunk chunk) { foreach (IBarData bar in chunk.Records.ToBarRecords()) { if (bar.Open.HasValue && bar.High.HasValue && bar.Low.HasValue && bar.Close.HasValue && bar.Timestamp.HasValue) { Console.WriteLine( "{0}: {1} OHLC {2} {3} {4} {5}", bar.Timestamp.Value.ToShortDateString(), chunk.Ric, bar.Open.Value.ToString("##.0000"), bar.High.Value.ToString("##.0000"), bar.Low.Value.ToString("##.0000"), bar.Close.Value.ToString("##.0000") ); }; } if (chunk.IsLast & chunk.Ric == "EUR=") { RequestTimeseries("GBP="); } //request = null; //Program.StopMessagePump(); } }
Morning Alex,
Your example works because the Main Method calls Launch() in TimeSeriesRequestExample which then sends the request , then returning to Main to call Dispatcher.PushFrame(). In the return Delegate you then fire a new request, after that the thread returns to the DispatcherFrame loop, so no code can be executed after that call, aside from in the return delegate. You can demonstrate this by trying to send a request after the Dispatcher.PushFrame() call and putting a breakpoint there, it wont be reached:
You can also see this by running the app and using breakall, you will see execution is stuck in that call.
I think I have found a work around. I will let you know.
Hi Again,
So what I thought would work wont. I dont see any way of getting this to work, any way I can think of to do it ends up blocking the calling thread in the Dispatcher.PushFrame method. And you cant call this on another thread.
Is this code work for you?
class Program { IRealtimeService realtime; public DispatcherFrame frame; static void Main(string[] args) { Program prog = new Program(); prog.run(); } public void PushFrame() { Dispatcher.ExitAllFrames(); frame = new DispatcherFrame(); Dispatcher.PushFrame(frame); } private void StopFrame() { frame.Continue = false; } public void run() { DataServicesFactory.Create("YourAppCode", OnDataServiceCreated); PushFrame(); IRealtimeDataRequest req1 = realtime.SetupDataRequest() .WithRic("JPY=") .WithFields(new string[2] { "BID", "ASK" }) .OnDataReceived(OnDataUpdate).CreateAndSend(); PushFrame(); IRealtimeDataRequest req2 = realtime.SetupDataRequest() .WithRic("THB=") .WithFields(new string[2] { "BID", "ASK" }) .OnDataReceived(OnDataUpdate).CreateAndSend(); PushFrame(); IRealtimeDataRequest req3 = realtime.SetupDataRequest() .WithRic("CNY=") .WithFields(new string[2] { "BID", "ASK" }) .OnDataReceived(OnDataUpdate).CreateAndSend(); PushFrame(); } public void OnDataServiceCreated(IDataServices dataservices) { Console.WriteLine("OnDataServiceCreated"); realtime = dataservices.Realtime; StopFrame(); } private void OnDataUpdate(IRealtimeUpdateDictionary update) { Console.WriteLine("OnDataUpdate"); foreach (var record in update) { Console.WriteLine("#### OnDataUpdate RIC: {0} ####", record.Key); foreach (var val in record.Value) { Console.WriteLine("{0} : {1}", val.Key, val.Value.Value.ToString()); } } Console.WriteLine(""); StopFrame(); } }
The output looks like:
OnDataServiceCreatedOnDataUpdate#### OnDataUpdate RIC: JPY= ####BID : +104.12ASK : +104.16OnDataUpdate#### OnDataUpdate RIC: THB= ####BID : +30.41ASK : +30.42OnDataUpdate#### OnDataUpdate RIC: CNY= ####BID : +6.5860ASK : +6.5875
Now I think I understand where you're coming from. Please correct me if I'm wrong, but I believe you got confused by the recommendation to do all data retrieval using Eikon .NET SDK on a single thread, which I'm guessing you interpreted as a recommendation to implement your entire application on a single thread. Retrieving data from Eikon on a single thread does not mean your application must be single threaded. It can be, if you'd like it. But it doesn't have to be. There's any number of ways to structure an application that retrieves data from Eikon using Eikon .NET SDK. You could for instance create a dedicated thread to house Eikon .NET SDK assemblies and continuously run the DispatcherFrame loop on that thread for as long as you need to retrieve data from Eikon.