Slow flushing (sending) of events - wpf

We are using Application Insights today to track events in our WPF solution.
Since this is a desktop we need to manually call the flush method.
Since we don't track an heap of events we keep flushing whenever an event come.
What we realised is that the flush method is very slow. What we've now done is moved this flush call to another thread, and hence need to keep alot of locks and checks, extra code.
Looking into the application insights code it comes down to these two methods:
private void DequeueAndSend()
{
lock (this.sendingLockObj)
{
IEnumerable<ITelemetry> telemetryItems = this.buffer.Dequeue();
try
{
// send request
this.Send(telemetryItems).ConfigureAwait(false).GetAwaiter().GetResult();
}
catch (Exception e)
{
CoreEventSource.Log.LogVerbose("DequeueAndSend: Failed Sending: Exception: " + e.ToString());
}
}
}
/// <summary>
/// Serializes a list of telemetry items and sends them.
/// </summary>
private async Task Send(IEnumerable<ITelemetry> telemetryItems)
{
if (telemetryItems == null || !telemetryItems.Any())
{
CoreEventSource.Log.LogVerbose("No Telemetry Items passed to Enqueue");
return;
}
byte[] data = JsonSerializer.Serialize(telemetryItems);
var transmission = new Transmission(this.endpointAddress, data, "application/x-json-stream", JsonSerializer.CompressionType);
await transmission.SendAsync().ConfigureAwait(false);
}
Looking specificly at this line:
this.Send(telemetryItems).ConfigureAwait(false).GetAwaiter().GetResult();
Not sure I'm getting this right but wouldn't the GetResult() make this method synchronous, if so, why is it implemented this way?
If not, what might be the reason for the Flush() method to be so slow?

Related

ReactiveCommand in WPF/ReactiveUI app blocks UI thread

I am quite a beginner with ReactiveUI and have a strange behavior with a ReactiveCommand.
I want to query data from a database that currently does not support
asynchronous operations. Since we want to exchange the database in the
future with an asynchronous interface I want to write everything as
if the database already would allow async operations. As far as I understand
that would mean that I wrap my database calls at the lowest level in
a Task.
I have a button which is bound to a ReactiveCommand and the command
starts the database query. While the query lasts I want to show some
sort of animation.
The problem is that whatever I tried, the query blocks my UI thread.
Here is part of my code:
public ReactiveCommand<Unit, Unit> StartExportCommand { get; }
//The constructor of my view model
public ExportDataViewModel(IDataRepository dr)
{
this.dr = dr;
//...
StartExportCommand = ReactiveCommand.CreateFromTask(() => StartExport());
//...
}
private async Task StartExport()
{
try
{
Status = "Querying data from database...";
//Interestingly without this call the Status message would not even be shown!
//The delay seems to give the system the opportunity to at least update the
//label in the UI that is bound to "Status".
await Task.Delay(100);
//### This is the call that blocks the UI thread for several seconds ###
var result = await dr.GetValues();
//do something with result...
Status = "Successfully completed";
}
catch(Exception ex)
{
Status = "Failed!";
//do whatever else is necessary
}
}
//This is the GetValues method of the implementation of the IDataRepository.
//The dictionary maps measured values to measuring points but that should not matter here.
//ValuesDto is just some container for the values.
public Task<IDictionary<int, ValuesDto>> GetValues()
{
//...
return Task<IDictionary<int, ValuesDto>>.Factory.StartNew(() =>
{
//### here is where the blocking calls to the database
//### specific APIs take place
return result;
}, TaskCreationOptions.LongRunning);
}
I don't understand why this code is blocking the UI thread although I am wrapping
the long running query in a Task.
Is there something wrong with this pattern or should I go another way with Observables?
Edit 1
I am aware of the fact that async != threads. I thought, however, that Task with the TaskCreationOptions.LongRunning would make the blocking code run on a thread pool thread.
Edit 2
As recommended by Andy I set a breakpoint inside my task and had a look into the Debug Threads window. It tells me that Task is running on a worker thread. Still my UI is blocking.

How to ensure wcf service client finishs his works in silverlight?

I use wcf service client to submit changes of data for a silverlight project. The correlative codes like this:
public class DispatcherCollection : UpdatableCollection<DocumentDispatcher>
{
public override void SubmitChanges()
{
DocumentServiceClient client = new DocumentServiceClient();
client.NewDocumentCompleted += (s, e) =>
{
// (s as DocumentServiceClient).CloseAsync();
// do something
};
client.UpdateColumnCompleted += (s, e) =>
{
// (s as DocumentServiceClient).CloseAsync();
// do something
};
client.RemoveDocumentCompleted += (s, e) =>
{
// (s as DocumentServiceClient).CloseAsync();
// do something
};
foreach (DocumentDispatcher d in this)
{
if (d.IsNew)
{
// d=>object[] data
client.NewDocumentAsync(data);
d.IsNew=false;
}
else
{
foreach (string propertyName in d.modifiedProperties)
{
client.UpdateColumnAsync(d.ID, GetPropertyValue(propertyName));
}
dd.ClearModifications();
}
}
foreach (DocumentDispatcher dd in removedItems)
{
client.RemoveDocumentAsync(dd.ID);
}
removedItems.Clear();
}
}
Class UpdatableCollection derives from ObserableCollection, and I implemtent logics in class DocumentDispatcher and UpdatableCollection to buffer the changes of data such as new created, property modified and removed. I use SubmitChanges method to submit all changes to server.
Now I am stuck:
1. I am at a loss when to close the client after a bunlde fo async calls. I don't know which callback is the last one.
2. What will happen when a user closes the IE immediately right after clicking the save button (it seems to be done because it runs async but in fact the updating threads are industriously running.)?
You can keep a counter or use an isbusy function to monitor the callbacks from your Async calls - to make sure they all finished.
If the user fires off a request to the WCF service, the WCF service will complete but there will be no call back - as the application will be closed.
I think that there is no wait handle for silverlight asynchornized call brings inconvenience. Here is my experence. I want to check and submit modifications of data which are not expicitly submitted when browser is closing. I have implemented codes in App_Exit like this:
private void Application_Exit(object sender, EventArgs e)
{
Document doc = EDPViewModel.CurrentViewModel.Document;
if (doc != null) new ServiceClient().SubmitChangesAsync(doc);
}
provided that in the SubmitChangesAsync method, not submitted modifications of doc are found out and submitted. Therefore, because of the asynchronized running features, while the service invoking is being sent, the application is yet immediately closed. And that will dispose related resouces of the application, including Service Invoking Tasks. So the codes above work not. I hope so eagerly that somewhere exists a mechanism, which can export a wait handle from silverlight asynchronized call, so that I can update the above codes whith this:
private void Application_Exit(object sender, EventArgs e)
{
Document doc = EDPViewModel.CurrentViewModel.Document;
if (doc != null)
{
Task t = new TaskFactory().StartNew(() => new ServiceClient().SubmitChangesAsync(doc));
t.Wait();
}
}
With wait operation I can really be sure that all modifications are really definitely submitted. So is there any similar pattern that can be used in silverlight?
It's for me a good news, as you put it, that calls could work like the mode "requesting and forgetting". So I needn' to worry too much about data losing during submitting.
To ensure all service calls are sent out before application is closed, I think, counter is a simple and effient idea. I will try to implement it in my project.
Thank you for your help!

Threads UI and nightmares

I have a class that handles some realtime action in a thread that it starts. There are other theads in play in this application as it is very complex. When This rt action starts i need to pop up a window and close it when it is done. Sounds easy.
There are events that I hook to when this action starts and stops. In those event handlers I place the code:
private void Voice_SpeakStarted(object sender, TMSpeakStartedEventArgs e)
{
InfoWindow = new Form();
InfoWindow.Show();
}
/// <summary>
/// this is the event handler speaking stops
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Voice_SpeakCompleted(object sender, TMSpeakCompletedEventArgs e)
{
if (InfoWindow.InvokeRequired)
{
InfoWindow.Invoke(new Action(() =>
{
InfoWindow.Close();
}));
InfoWindow.Hide();
}
}
There are times I get an error that the thread has terminated. (An error occurred invoking the method. The destination thread no longer exists.)
I always seem to get the window to show. I can not seem to get the window to close.
I also see that sometime the handler themselves do not get called.
I need help bad. I can post more code if it would be helpful.
Edited - added more code
This is how I start the class
public void start()
{
//It's already alive, nothing to do
if (alive) return;
//Make sure this is the only place where alive is set to true
alive = true;
Voice.SpeakCompleted += new Speech.TMSpeakCompletedDelegate(Voice_SpeakCompleted);
Voice.SpeakStarted += new Speech.TMSpeakStartedDelegate(Voice_SpeakStarted);
dispatch = new Thread(new ThreadStart(ProcessSayList));
dispatch.Start();
}
The constructor of the class is
public AnimationControl(dynamic parent)
{
Parent = parent;
Voice = new Speech();
q = Queue.Synchronized(new Queue(1000));
start();
}
You should really specialize your thread and stop calling code managed by other thread form any thread. Use message queues to communicate actions to your thread. This is the safest way to do multi-threading.
Example in pseudo-code:
Thread1
{
while (1)
{
read my last message in my queue;
do something according to this message like:
openwindow();
or closewindow();
}
}
Thread2
{
My life is short, I just need to post a message to thread1
}
Thread3
{
etc.
}
There are ready-to-use structures for such a thing on every system. And by doing so, it will be much more easy to understand what's happening in case of problem like that. Of course, if you don't take care, your threaded program can become absolutely linear; the goal is to make sure some parts of actions can be made in parallel and do not create a chain of threads waiting each other, one by one :)
Check my answer here for some information on the thread terminated error, and UI threading in general: understanding InvalidAsynchronousStateException occurrences
Well for one thing you're calling Hide on your window on the wrong thread even if InvokeRequired returns true.
I can also guess that you're creating your Voice instance on a new thread and returning when you get a "close" message, thus sometimes killing the thread you're trying to route windows messages through. Consider holding on to the thread until your window is actually closed.
And yes, you should post more code, there isn't a single line of code that shows how you create/dispose of that thread.

WCF/Silverlight: How can I foul a Channel?

I was told that I shouldn't cache channels in Silverlight/WCF because they may become faulted and unsuable. Can somone show me some sample code that would prove it can happen.
Call a service to prove the connection can work (i.e. no bogus URL)
Make a second call that fouls the channel by causing it to go into a faulted condition
Repeat the first call, which would fail.
In my own testing, the key is whether the binding you're using is session-oriented or not. If you're using a stateless binding like BasicHttpBinding, you can muck up the channel all you want and you're good. For instance, I've got a WCF service using the BasicHttpBinding that looks like this -- note specifically the Channel.Abort() call in SayGoodbye():
public class HelloWorldService : IHelloWorldService
{
public string SayHello()
{
return "Hello.";
}
public string SayGoodbye()
{
OperationContext.Current.Channel.Abort();
return "Goodbye.";
}
}
And the Silverlight client code looks like this (ugly as hell, sorry).
public partial class ServiceTestPage : Page
{
HelloWorldServiceClient client;
public ServiceTestPage()
{
InitializeComponent();
client = new HelloWorldServiceClient();
client.SayHelloCompleted += new EventHandler<SayHelloCompletedEventArgs>(client_SayHelloCompleted);
client.SayGoodbyeCompleted += new EventHandler<SayGoodbyeCompletedEventArgs>(client_SayGoodbyeCompleted);
client.SayHelloAsync();
}
void client_SayHelloCompleted(object sender, SayHelloCompletedEventArgs e)
{
if (e.Error == null)
{
Debug.WriteLine("Called SayHello() with result: {0}.", e.Result);
client.SayGoodbyeAsync();
}
else
{
Debug.WriteLine("Called SayHello() with the error: {0}", e.Error.ToString());
}
}
void client_SayGoodbyeCompleted(object sender, SayGoodbyeCompletedEventArgs e)
{
if (e.Error == null)
{
Debug.WriteLine("Called SayGoodbye() with result: {0}.");
}
else
{
Debug.WriteLine("Called SayGoodbye() with the error: {0}", e.Error.ToString());
}
client.SayHelloAsync(); // start over
}
}
And it'll loop around infinitely as long as you want.
But if you're using a session-oriented binding like Net.TCP or HttpPollingDuplex, you've got to be much more careful about your channel handling. If that's the case, then of course you're caching your proxy client, right? What you have to do in that instance is to catch the Channel_Faulted event, abort the client, and then recreate it, and of course, re-establish all your event-handlers. Kind of a pain.
On a side note, when it comes to using a duplex binding, the best approach that I've found (I'm open to others) is to create a wrapper around my proxy client that does three things:
(1) Transforms the obnoxious event-raising code generated by the "Add Service Reference" dialog box into a far-more-useful continuation-passing pattern.
(2) Wraps each of the events raised from the server-side, so that the client can subscribe to the event on my wrapper, not the event on the proxy client itself, since the proxy client itself may have to be deleted and recreated.
(3) Handles the ChannelFaulted event, and (several times, with a timeout) attempts to recreate the proxy client. If it succeeds, it automatically resubscribes all of its event wrappers, and if it fails, it throws a real ClientFaulted event which in effect means, "You're screwed, try again later."
It's a pain, since it seems like this is the sort of thing that should have been included with the MS-generated code in the first place. But it sure fixes a whole lot of problems. One of these days I'll see if I can get this wrapper working with T4 templates.

Calling a webservice synchronously from a Silverlight 3 application?

I am trying to reuse some .NET code that performs some calls to a data-access-layer type service. I have managed to package up both the input to the method and the output from the method, but unfortunately the service is called from inside code that I really don't want to rewrite in order to be asynchronous.
Unfortunately, the webservice code generated in Silverlight only produces asynchronous methods, so I was wondering if anyone had working code that managed to work around this?
Note: I don't need to execute the main code path here on the UI thread, but the code in question will expect that calls it makes to the data access layers are synchronous in nature, but the entire job can be mainly executing on a background thread.
I tried the recipe found here: The Easy Way To Synchronously Call WCF Services In Silverlight, but unfortunately it times out and never completes the call.
Or rather, what seems to happen is that the completed event handler is called, but only after the method returns. I am suspecting that the event handler is called from a dispatcher or similar, and since I'm blocking the main thread here, it never completes until the code is actually back into the GUI loop.
Or something like that.
Here's my own version that I wrote before I found the above recipe, but it suffers from the same problem:
public static object ExecuteRequestOnServer(Type dalInterfaceType, string methodName, object[] arguments)
{
string securityToken = "DUMMYTOKEN";
string input = "DUMMYINPUT";
object result = null;
Exception resultException = null;
object evtLock = new object();
var evt = new System.Threading.ManualResetEvent(false);
try
{
var client = new MinGatServices.DataAccessLayerServiceSoapClient();
client.ExecuteRequestCompleted += (s, e) =>
{
resultException = e.Error;
result = e.Result;
lock (evtLock)
{
if (evt != null)
evt.Set();
}
};
client.ExecuteRequestAsync(securityToken, input);
try
{
var didComplete = evt.WaitOne(10000);
if (!didComplete)
throw new TimeoutException("A data access layer web service request timed out (" + dalInterfaceType.Name + "." + methodName + ")");
}
finally
{
client.CloseAsync();
}
}
finally
{
lock (evtLock)
{
evt.Close();
evt = null;
}
}
if (resultException != null)
throw resultException;
else
return result;
}
Basically, both recipes does this:
Set up a ManualResetEvent
Hook into the Completed event
The event handler grabs the result from the service call, and signals the event
The main thread now starts the web service call asynchronously
It then waits for the event to become signalled
However, the event handler is not called until the method above has returned, hence my code that checks for evt != null and such, to avoid TargetInvocationException from killing my program after the method has timed out.
Does anyone know:
... if it is possible at all in Silverlight 3
... what I have done wrong above?
I suspect that the MinGatServices thingy is trying to be helpful by ensuring the ExecuteRequestCompleted is dispatched on the main UI thread.
I also suspect that your code is already executing on the main UI thread which you have blocked. Never block the UI thread in Silverlight, if you need to block the UI use something like the BusyIndicator control.
The knee-jerk answer is "code asynchronously" but that doesn't satisfy your question's requirement.
One possible solution that may be less troublesome is to start the whole chunk of code from whatever user action invokes it on a different thread, using say the BackgroundWorker.
Of course the MinGatServices might be ensuring the callback occurs on the same thread that executed ExecuteRequestAsync in which case you'll need to get that to run on a different thread (jumping back to the UI thread would be acceptable):-
Deployment.Current.Dispatcher.BeginInvoke(() => client.ExecuteRequestAsync(securityToken, input));

Resources