how to set time of web service in windows phone - web-services

i have a web service.
it takes 10-15 seconds to upload completely. But some time due to slow internet connection it takes more than 15 second.
I want to open a message box or pop up box which open when the service takes more than 15 seconds, to display message "Slow Internet Connection".
How can i add timer in my code so that a pop up block open(Or alert says Slow Connection) on page load event when web service takes time more than 15 second to load ?
Please help me on this...
public Quiz()
{
InitializeComponent();
DispatchTimer timer = new DispatcherTimer();
int serviceCount = 15;
Loaded += Quiz_Loaded;
}
protected void Quiz_Loaded(object sender, RoutedEventArgs e)
{
SystemTray.ProgressIndicator = new ProgressIndicator();
SystemTray.ProgressIndicator.IsIndeterminate = true;
SystemTray.ProgressIndicator.IsVisible = true;
SystemTray.ProgressIndicator.Text = "Loading Questions...";
pg2.Visibility = Visibility.Visible;
txtloading.Visibility = Visibility.Visible;
if (!timer.IsEnabled)
{
timer.Tick += timer_Tick;
timer.Interval = new TimeSpan(0, 0, 1);
timer.Start();
}
}
void timer_Tick(object sender, object e)
{
serviceCount--;
if (serviceCount < 15)
{
PostData();
}
else
{
txtloading.Text = "slow connection.....";
}
}
private void PostData()
{
Uri uri = new Uri("my web service url");
string data = "device_id=test123&quiz_type=all";
WebClient wc = new WebClient();
wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
wc.UploadStringAsync(uri, data);
wc.UploadStringCompleted += wc_UploadComplete;
}
public void wc_UploadComplete(object sender, UploadStringCompletedEventArgs e)
{
var rootObject = JsonConvert.DeserializeObject<RootObject>(e.Result);
question = rootObject.questions;
DisplayQuestion();
SystemTray.ProgressIndicator.IsVisible = false;
pg2.Visibility = Visibility.Collapsed;
txtloading.Visibility = Visibility.Collapsed;
}
i want to call message block when web service takes time more than 15 second. & also have a retry button which reload the page again to get all data from service..

You could use a DispatcherTimer that is initialized whenever the first call to the web service is initiated. That way, whenever a given timespan elapses, you can trigger a custom action (such as a notification).

Related

Google Custom Metrics tracking of latency data

I'm using external service, based on REST calls, and I want to track the time that took the service to respond to my requests. My code is written with C# (core v2.2)
I planning to count times for all the HTTP requests (with Stopwatch) and keep this information in a List<long>. Every 60 seconds I will write the tracked information from the list to Google Custom Metrics.
In the end, I expect to see the AVERAGE time of execution in a graph.
This is my code so far:
public class CustomMetricsWritter
{
public CustomMetricsWritter(string projectId)
{
this.Client = MetricServiceClient.Create();
this.ProjectId = projectId;
}
private MetricServiceClient Client { get; set; }
public string ProjectId { get; private set; }
public object CreateMetric(string metricType, string title, string description, string unit)
{
// Prepare custom metric descriptor.
MetricDescriptor metricDescriptor = new MetricDescriptor();
metricDescriptor.DisplayName = title;
metricDescriptor.Description = description;
metricDescriptor.MetricKind = MetricKind.Gauge;
metricDescriptor.ValueType = MetricDescriptor.Types.ValueType.Double;
metricDescriptor.Type = metricType;
metricDescriptor.Unit = unit;
CreateMetricDescriptorRequest request = new CreateMetricDescriptorRequest
{
ProjectName = new ProjectName(this.ProjectId),
};
request.MetricDescriptor = metricDescriptor;
// Make the request.
return Client.CreateMetricDescriptor(request);
}
public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public async Task WriteTimeSeriesDataAsync(string metricDescriptor, TypedValue[] points, string machineName)
{
// Initialize request argument(s).
ProjectName name = new ProjectName(this.ProjectId);
// Prepare a data point.
Timestamp timeStamp = new Timestamp();
timeStamp.Seconds = (long)(DateTime.UtcNow - UnixEpoch).TotalSeconds;
TimeInterval interval = new TimeInterval();
interval.EndTime = timeStamp;
// Prepare monitored resource.
MonitoredResource resource = new MonitoredResource();
resource.Type = "global";
resource.Labels.Add("project_id", this.ProjectId);
// Add newly created time series to list of time series to be written.
List<TimeSeries> timeSeries = new List<TimeSeries>(points.Length);
// Prepare custom metric.
Metric metric = new Metric();
metric.Type = metricDescriptor;
metric.Labels.Add("machine", machineName);
// Create a new time series using inputs.
TimeSeries timeSeriesData = new TimeSeries();
timeSeriesData.Metric = metric;
timeSeriesData.Resource = resource;
foreach (var point in points)
{
Point dataPoint = new Point();
dataPoint.Value = point;
dataPoint.Interval = interval;
timeSeriesData.Points.Add(dataPoint);
}
timeSeries.Add(timeSeriesData);
// Write time series data.
await this.Client.CreateTimeSeriesAsync(name, timeSeries).ConfigureAwait(false);
}
}
I running this class with this code (create the metric and then fill it with dummy values):
try
{
CustomMetricsWritter customMetricsWriter = new CustomMetricsWritter(Consts.GOOGLE_CLOUD_PROJECT);
string metric = "custom.googleapis.com/web/latency";
customMetricsWriter.CreateMetric(metric, "Execution Latency", "Calling REST service (MS).", "{INT64}");
// Exception thrown in the next line ----->
await customMetricsWriter.WriteTimeSeriesDataAsync(
metric,
new TypedValue[] {
new TypedValue(){ Int64Value = 150},
new TypedValue(){ Int64Value = 250},
new TypedValue(){ Int64Value = 350},
},
"my-machine-type");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
throw;
}
I getting back this thrown exception:
Grpc.Core.RpcException: Status(StatusCode=InvalidArgument, Detail="One or more TimeSeries could not be written: Field timeSeries[0].points had an invalid value: Only one point can be written per TimeSeries per request.: timeSeries[0]")
at Google.Api.Gax.Grpc.ApiCallRetryExtensions.<>c__DisplayClass0_0`2.<<WithRetry>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at ***.CustomMetricsWritter.WriteTimeSeriesDataAsync(String metricDescriptor, TypedValue[] points, String machineName) in ***\GoogleCloud\CustomMetricsWritter.cs:line 131
at Test.Program.MainAsync() in ***\Test\Program.cs:line 156
What I'm doing wrong?
I'm not a C# expert, but there are examples here:
https://github.com/GoogleCloudPlatform/dotnet-docs-samples/blob/master/monitoring/api/QuickStart/QuickStart.cs

How to use sync token on Google People API

I cannot really find an example on how to use this.
Right now, I'm doing like this:
// Request 10 connections.
ListConnectionsResponse response = peopleService.people().connections()
.list("people/me")
.setRequestSyncToken(true)
.setPageSize(10)
.setPersonFields("names,emailAddresses")
.execute();
I make some changes to my contacts (adding, removing, updating), then I do this:
// Request 10 connections.
ListConnectionsResponse response2 = peopleService.people().connections()
.list("people/me")
.setSyncToken(response.getNextSyncToken())
.setPageSize(10)
.setPersonFields("names,emailAddresses")
.execute();
But it seems like I cannot get the changes I've done earlier, not even if I do them directly from the UI. I'm pretty sure I'm using the sync token in the wrong way.
Update (19/02/2020): In this example I call the API requesting the sync token in the first request (I successfully get the contacts), pause the execution (by breakpoint), delete a contact and update another one (from the web page), resume the execution and then I call the API again with the sync token that I extracted from the previous call. The result is that no change was made for some reason:
// Build a new authorized API client service.
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
PeopleService peopleService = new PeopleService.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT))
.setApplicationName(APPLICATION_NAME)
.build();
// Request 10 connections.
ListConnectionsResponse response = peopleService.people().connections()
.list("people/me")
.setPageSize(10)
.setPersonFields("names,emailAddresses")
.setRequestSyncToken(true)
.execute();
// Print display name of connections if available.
List<Person> connections = response.getConnections();
if (connections != null && connections.size() > 0) {
for (Person person : connections) {
List<Name> names = person.getNames();
if (names != null && names.size() > 0) {
System.out.println("Name: " + person.getNames().get(0)
.getDisplayName());
} else {
System.out.println("No names available for connection.");
}
}
} else {
System.out.println("No connections found.");
}
// CORRECT: 2 CONTACTS PRINTED
// CORRECT: THE SYNC TOKEN IS THERE
String syncToken = response.getNextSyncToken();
System.out.println("syncToken = "+syncToken);
// I SETUP A BREAKPOINT BELOW, I DELETE ONE CONTACT AND EDIT ANOTHER AND THEN I RESUME THE EXECUTING
// Request 10 connections.
response = peopleService.people().connections()
.list("people/me")
.setPageSize(10)
.setPersonFields("names,emailAddresses")
.setSyncToken(syncToken)
.execute();
// Print display name of connections if available.
connections = response.getConnections();
if (connections != null && connections.size() > 0) {
for (Person person : connections) {
List<Name> names = person.getNames();
if (names != null && names.size() > 0) {
System.out.println("Name: " + person.getNames().get(0)
.getDisplayName());
} else {
System.out.println("No names available for connection.");
}
}
} else {
System.out.println("No connections found.");
}
// WRONG: I GET "NO CONNECTIONS FOUND"
Something I've found out is that, when requesting or setting a sync token, you must iterate the entirety of the contacts for the nextSyncToken to be populated.
That means that as long as there is a nextPageToken (wink wink setPageSize(10)), the sync token will not be populated.
You could either:
A) Loop over all the contacts using your current
pagination, doing whatever you need to do at every
iteration, and after the last call retrieve the populated
sync token.
B) Iterate over all the contacts in one go, using the max
page size of 2000 and a single personField, retrieve the
token, and then do whatever you need to do. Note that if
you are expecting a user to have more than 2000
contacts, you will still need to call the next pages using
the nextPageToken.
Here is an exemple of a sync loop, adapted from Synchronize Resources Efficiently. Note that I usually use the Python client, so this Java code might not be 100% error free:
private static void run() throws IOException {
Request request = people_service.people().connections()
.list("people/me")
.setPageSize(10)
.setPersonFields("names,emailAddresses");
// Load the sync token stored from the last execution, if any.
// The syncSettingsDataStore is whatever you use for storage.
String syncToken = syncSettingsDataStore.get(SYNC_TOKEN_KEY);
String syncType = null;
// Perform the appropiate sync
if (syncToken == null) {
// Perform a full sync
request.setRequestSyncToken(true);
syncType = "FULL";
} else {
// Try to perform an incremental sync.
request.setSyncToken(syncToken);
syncType = "INCREMENTAL";
}
String pageToken = null;
ListConnectionsResponse response = null;
List<Person> contacts = null;
// Iterate over all the contacts, page by page.
do {
request.setPageToken(pageToken);
try {
response = request.execute();
} catch (GoogleJsonResponseException e) {
if (e.getStatusCode() == 410) {
// A 410 status code, "Gone", indicates that the sync token is
// invalid/expired.
// WARNING: The code is 400 in the Python client. I think the
// Java client uses the correct code, but be on the lookout.
// Clear the sync token.
syncSettingsDataStore.delete(SYNC_TOKEN_KEY);
// And anything else you need before re-syncing.
dataStore.clear();
// Restart
run();
} else {
throw e;
}
}
contacts = response.getItems();
if (contacts.size() == 0) {
System.out.println("No contacts to sync.");
} else if (syncType == "FULL"){
//do full sync for this page.
} else if (syncType == "INCREMENTAL") {
//do incremental sync for this page.
} else {
// What are you doing here???
}
pageToken = response.getNextPageToken();
} while (pageToken != null);
// Store the sync token from the last request for use at the next execution.
syncSettingsDataStore.set(SYNC_TOKEN_KEY, response.getNextSyncToken());
System.out.println("Sync complete.");
}

How to check if Google Glass is connected to internet using GDK

Is there a way to detect if Google Glass is connected to the internet at runtime? For instance, I often get the message "Can't reach Google right now" when using voice input in my app. Instead, I would like to preemptively intercept the condition that would cause that message and use default values rather than ask for voice input. After searching for a while, the only thing I could find was a solution to the same question for Android in general:
private boolean isConnected() {
ConnectivityManager connectivityManager
= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
I tried using this for my Glassware but it doesn't seem to work (I turned off the wifi and data but isConnected() still returns true even though I get the "Can't reach Google right now" message). Does anyone know if the GDK has a way to do this? Or should something similar to the above method work?
EDIT: Here's my eventual solution, based partially on the answer by EntryLevelDev below.
I had to use a background thread to use HTTP GET requests to avoid getting a NetworkOnMainThreadException, so I decided to have it run every few seconds and update a local isConnected variable:
public static boolean isConnected = false;
public boolean isDeviceConnectedToInternet() {
return isConnected;
}
private class CheckConnectivityTask extends AsyncTask<Void, Boolean, Boolean> {
protected Boolean doInBackground(Void... voids) {
while(true) {
// Update isConnected variable.
publishProgress(isConnected());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* Determines if the Glassware can access the internet.
* isNetworkAvailable() is used first because there is no point in executing an HTTP GET
* request if ConnectivityManager and NetworkInfo tell us that no network is available.
*/
private boolean isConnected(){
if (isNetworkAvailable()) {
HttpGet httpGet = new HttpGet("http://www.google.com");
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, 3000);
HttpConnectionParams.setSoTimeout(httpParameters, 5000);
DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
try{
Log.d(LOG_TAG, "Checking network connection...");
httpClient.execute(httpGet);
Log.d(LOG_TAG, "Connection OK");
return true;
}
catch(ClientProtocolException e){
e.printStackTrace();
}
catch(IOException e){
e.printStackTrace();
}
Log.d(LOG_TAG, "Connection unavailable");
} else {
// No connection; for Glass this probably means Bluetooth is disconnected.
Log.d(LOG_TAG, "No network available!");
}
return false;
}
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager
= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
Log.d(LOG_TAG, String.format("In isConnected(), activeNetworkInfo.toString(): %s",
activeNetworkInfo == null ? "null" : activeNetworkInfo.toString()));
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
protected void onProgressUpdate(Boolean... isConnected) {
DecisionMakerService.isConnected = isConnected[0];
Log.d(LOG_TAG, "Checking connection: connected = " + isConnected[0]);
}
}
To start it, call new CheckConnectivityTask().execute(); (probably from onCreate()). I also had to add these to my Android.manifest:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
If Glass connects to a phone with Bluetooth, your method returns true even when your phone has no WiFi and data connection.
I guess it's a correct behavior. getActiveNetworkInfo is more about a connection via available interfaces. It's not really about connection to the internet. It's like connecting to a router doesn't mean you connect to the internet.
NOTE (from the doc):
getActiveNetworkInfo returns
"a NetworkInfo object for the current default network or null if no network default network is currently active"
To check the internet connection, you might try ping Google instead though I think there might be a better way to check.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
#Override
public void run() {
Log.v(MainActivity.class.getSimpleName(), "isGoogleReachable : "
+ isGoogleReachable());
}
}).start();;
}
private boolean isGoogleReachable() {
try {
if (InetAddress.getByName("www.google.com").isReachable(5000)) {
return true;
} else {
return false;
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
}
Add this permission:
<uses-permission android:name="android.permission.INTERNET" />
EDIT:
Or you could try this:
public static void isNetworkAvailable(Context context){
HttpGet httpGet = new HttpGet("http://www.google.com");
HttpParams httpParameters = new BasicHttpParams();
// Set the timeout in milliseconds until a connection is established.
// The default value is zero, that means the timeout is not used.
int timeoutConnection = 3000;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
// Set the default socket timeout (SO_TIMEOUT)
// in milliseconds which is the timeout for waiting for data.
int timeoutSocket = 5000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
try{
Log.d(TAG, "Checking network connection...");
httpClient.execute(httpGet);
Log.d(TAG, "Connection OK");
return;
}
catch(ClientProtocolException e){
e.printStackTrace();
}
catch(IOException e){
e.printStackTrace();
}
Log.d(TAG, "Connection unavailable");
}
Also see:
Detect if Android device has Internet connection
"should something similar to the above method work?"
Yes, it works fine if Bluetooth is also off.
When you have wifi and data turned off, what is the network type name that activeNetworkInfo.getTypeName() returns?
This might be a bug — can you dump as much info as possible out of the NetworkInfo object (especially the type name, DetailedState enumeration, and so forth) and file it in our issue tracker?

Why does SQL Server CLR procedure hang in GetResponse() call to web service

Environment: C#, .Net 3.5, Sql Server 2005
I have a method that works in a stand-alone C# console application project. It creates an XMLElement from data in the database and uses a private method to send it to a web service on our local network. When run from VS in this test project, it runs in < 5 seconds.
I copied the class into a CLR project, built it, and installed it in SQL Server (WITH PERMISSION_SET = EXTERNAL_ACCESS). The only difference is the SqlContext.Pipe.Send() calls that I added for debugging.
I am testing it by using an EXECUTE command one stored procedure (in the CLR) from an SSMS query window. It never returns. When I stop execution of the call after a minute, the last thing displayed is "Calling GetResponse() using http://servername:53694/odata.svc/Customers/". Any ideas as to why the GetResponse() call doesn't return when executing within SQL Server?
private static string SendPost(XElement entry, SqlString url, SqlString entityName)
{
// Send the HTTP request
string serviceURL = url.ToString() + entityName.ToString() + "/";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(serviceURL);
request.Method = "POST";
request.Accept = "application/atom+xml,application/xml";
request.ContentType = "application/atom+xml";
request.Timeout = 20000;
request.Proxy = null;
using (var writer = XmlWriter.Create(request.GetRequestStream()))
{
entry.WriteTo(writer);
}
try
{
SqlContext.Pipe.Send("Calling GetResponse() using " + request.RequestUri);
WebResponse response = request.GetResponse();
SqlContext.Pipe.Send("Back from GetResponse()");
/*
string feedData = string.Empty;
Stream stream = response.GetResponseStream();
using (StreamReader streamReader = new StreamReader(stream))
{
feedData = streamReader.ReadToEnd();
}
*/
HttpStatusCode StatusCode = ((HttpWebResponse)response).StatusCode;
response.Close();
if (StatusCode == HttpStatusCode.Created /* 201 */ )
{
return "Created # Location= " + response.Headers["Location"];
}
return "Creation failed; StatusCode=" + StatusCode.ToString();
}
catch (WebException ex)
{
return ex.Message.ToString();
}
finally
{
if (request != null)
request.Abort();
}
}
The problem turned out to be the creation of the request content from the XML. The original:
using (var writer = XmlWriter.Create(request.GetRequestStream()))
{
entry.WriteTo(writer);
}
The working replacement:
using (Stream requestStream = request.GetRequestStream())
{
using (var writer = XmlWriter.Create(requestStream))
{
entry.WriteTo(writer);
}
}
You need to dispose the WebResponse. Otherwise, after a few calls it goes to timeout.
You are asking for trouble doing this in the CLR. And you say you are calling this from a trigger? This belongs in the application tier.
Stuff like this is why when the CLR functionality came out, DBAs were very concerned about how it would be misused.

Excel RTD (Real Time Data) client other than Excel?

I have been looking all over, and couldn't find any example for an RTD CLIENT (many RTD server samples, though).
My goal is to 'pull' data from an RTD server into my application for algo-trading purposes.
If possible, without using C# / .Net, as I am looking for a lightweight, deploy-able solution.
Can you give me any tips?
Here is a C# client I built as a test harness for Excel RTD servers (both in-process DLL and out-of-process EXE):
using System;
using System.Reflection;
using System.Threading;
namespace MyRTD
{
class Program
{
// ProgIDs for COM classes.
private const String RTDProgID = "MyRTD.RTD";
private const String RTDUpdateEventProgID = "MyRTD.UpdateEvent";
private const String RTDEXEProgID = "MyRTDEXE.RTD";
private const String RTDEXEUpdateEventProgID = "MyRTDEXE.UpdateEvent";
// Dummy topic.
private const int topicID = 12345;
private const String topic = "topic";
static void Main(string[] args)
{
Console.WriteLine("Test in-process (DLL) RTD server.");
TestMyRTD(RTDProgID,RTDUpdateEventProgID);
Console.WriteLine("Test out-of-process (EXE) RTD server.");
TestMyRTD(RTDEXEProgID,RTDEXEUpdateEventProgID);
Console.WriteLine("Press enter to exit ...");
Console.ReadLine();
}
static void TestMyRTD(String rtdID, String eventID)
{
try
{
// Create the RTD server.
Type rtd;
Object rtdServer = null;
rtd = Type.GetTypeFromProgID(rtdID);
rtdServer = Activator.CreateInstance(rtd);
Console.WriteLine("rtdServer = {0}", rtdServer.ToString());
// Create a callback event.
Type update;
Object updateEvent = null;
update = Type.GetTypeFromProgID(eventID);
updateEvent = Activator.CreateInstance(update);
Console.WriteLine("updateEvent = {0}", updateEvent.ToString());
// Start the RTD server.
Object[] param = new Object[1];
param[0] = updateEvent;
MethodInfo method = rtd.GetMethod("ServerStart");
Object ret; // Return value.
ret = method.Invoke(rtdServer, param);
Console.WriteLine("ret for 'ServerStart()' = {0}", ret.ToString());
// Request data from the RTD server.
Object[] topics = new Object[1];
topics[0] = topic;
Boolean newData = true; // Request new data, not cached data.
param = new Object[3];
param[0] = topicID;
param[1] = topics;
param[2] = newData;
method = rtd.GetMethod("ConnectData");
ret = method.Invoke(rtdServer, param);
Console.WriteLine("ret for 'ConnectData()' = {0}", ret.ToString());
// Loop and wait for RTD to notify (via callback) that
// data is available.
int count = 0;
do
{
count++;
// Check that the RTD server is still alive.
Object status;
param = null;
method = rtd.GetMethod("Heartbeat");
status = method.Invoke(rtdServer, param);
Console.WriteLine("status for 'Heartbeat()' = {0}", status.ToString());
// Get data from the RTD server.
int topicCount = 0;
param = new Object[1];
param[0] = topicCount;
method = rtd.GetMethod("RefreshData");
Object[,] retval = new Object[2, 1];
retval = (Object[,])method.Invoke(rtdServer, param);
Console.WriteLine("retval for 'RefreshData()' = {0}", retval[1,0].ToString());
// Wait for 2 seconds before getting
// more data from the RTD server.
Thread.Sleep(2000);
} while (count < 5); // Loop 5 times.
// Disconnect from data topic.
param = new Object[1];
param[0] = topicID;
method = rtd.GetMethod("DisconnectData");
method.Invoke(rtdServer, param);
// Shutdown the RTD server.
param = null;
method = rtd.GetMethod("ServerTerminate");
method.Invoke(rtdServer, param);
}
catch (Exception e)
{
Console.WriteLine("Error: {0} ", e.Message);
}
}
}
}
You can indeed create RTD "clients" outside Excel by emulating the calls that Excel would make to the RTD server. The RTD server is, after all, just a COM component that implements IRtdServer (and IRTDUpdateEvent for the callback).
You must follow the call sequence that Excel itself uses when interacting with the RTD. But once you do that, the RTD should quite happily pump data into your "client". Indeed, there might be an advantage to doing this because whereas Excel will only pull data from the RTD about every two seconds, your client can pull data as fast as it wants. This is certainly an advantage for algorithmic trading.
Whether such a client can work side-by-side with Excel is something I have not tested.
You would use RTD because RTD is normally free and the API access adds $100/month/cient or more to the datafeed cost for the dataservice we are using