StreamInsight: CleanseInput drops events - c#

I got an issue and I don't know why it appears.
I have a InputAdapter which receives randomly generated events for testing purposes.
The following code creates a query which drops a lot of events. which I actually want to be kept.
var atgs = new AdvanceTimeGenerationSettings(config.Input.EventCount,
TimeSpan.FromSeconds(config.Input.Delay), true);
var ats = new AdvanceTimeSettings(atgs, null, AdvanceTimePolicy.Adjust);
var dstream = CepStream<Dataclass>.Create("Data Input Stream", typeof (InAdapterFactory),
config.Input, EventShape.Point, ats);
Query output = dstream.ToQuery(myApplication,
"Sample unbounded query",
"Query with no output adapter",
EventShape.Point,
StreamEventOrder.FullyOrdered);
output.Start();
var instream = output.ToStream<Dataclass>();
Does anyone have an idea why between the DataInputStream and DatainputStream_CleanseInput only a fifth of all events get passed through? See the following pic. Is there a way to avoid that?
https://dl.dropboxusercontent.com/u/15482726/CleanseIssue.jpg
I am very grateful for any help.
Best regards,
Joe

Those are going to be events dropped due to CTI violations. While you have your AdvanceTimePolicy set to Adjust, this only applies to Interval events that cross the CTI span in question. That is, if the Interval event has a start time before the last-issued CTI and an end time after the last-issued CTI, the start time (only) of the Interval event will be adjusted. Point events are always dropped.

Related

IGeolocator's PositionChanged firing twice?

Context
I'm developing a traffic management app using C# (Xamarin Forms) which requires a constant feed of the user's location.
Plugin
I'm using the Geolocator plugin by James Montemagno and the PositionChanged event on the IGeolocator interface seems to be triggering twice when a position change occurs.
Device
I'm currently debugging on an Android Emulator on Visual Studio Enterprise v15.5.3
Steps to reproduce the behaviour
1) After instantiating the locator object:
IGeolocator locator = CrossGeolocator.Current
2) Some code for when the locator's PositionChanged is triggered:
locator.PositionChanged += (sender,e) => {
// Testing its frequency
System.Diagnostics.Debug.WriteLine("Position Changed Triggered.");
}
3) Start listening in an async Task function
locator.DesiredAccuracy = 100;
if(!locator.isListening)
await locator.StartListeningAsync(TimeSpan.FromMilliseconds(500), 1, true);
4) Send coordinates via the emulator
Expected Results
The output window should display one message saying "Position Changed Triggered".
Actual Results
The output window has two identical messages printed, saying: "Position Changed Triggered".
Why is this happening? and how can I make it so that the event is ONLY triggered/handled ONCE for every time the position is actually changed.
What I've tried so far
Googled the issue, not many identical situations found.
Saw an explanation here which makes me believe it's the emulator has something to do with it, although I found the solution a bit ambiguous and am not sure what they're referring to with "Live/Pin Mode"
Created a separate function and assigned the event to it, then removed it after calling my code. This does cause it to execute once, but it never executes again unless I reassign in. And if I do, sure enough the code will run for the second time, resulting in the same initial problem.
Tried setting a boolean to check if it has already run once, but realised not long after how that's illogical.
Tried to set a DateTime object to make sure no more than 1 event occurs in a given time frame; this was also no good.
Help would be appreciated. Thanks.
Please note that the location service might deliver a location event more than one time (more here).
Even if the location service is not delivering the location event more than one time, usage and/or implementation of the API (Geolocator plugin) might cause reception of the location event more than one time from the API.
In the app you might check the location event properties (accuracy, location timestamp, order of event received, etc.). Use the "best" location event with "best" meaning preferred accuracy, most recent timestamp, or the first received location event if timestamp and accuracy are equal.

Reactive Extensions - Flushing Subject / IObservable in a synchronous fashion

EDIT: I've edited a few lines of code, when running in the IDE it fails without an error or anything.
I'm new to Reactive Extensions and have a problem that I am trying to sort out. I'm using RX to queue events on a machine, then every so often send that data to a server. My problem appears to be that when the application is shutting down, anything that is an async call of any sort seems to just cancel and not run, thus the last batch of events never gets sent.
I have a Subject, where Event is my data class. I know now that a Subject might not be the best class to use, but here we are.
My code looks mostly like the following, added a few comments for clarity:
IObservable<IList<Event>> eventsObserver = Instance.EventBuffer.ToList<Event>();
var eventsEnumerable = eventsObserver.ToEnumerable();
List<Event> events = new List<Event>();
try
{
events = (List<Event>)eventsEnumerable.First(); // THIS LINE FAILS SILENTLY, EVEN IN DEBUGGER...
}
catch(Exception ex)
{
System.Diagnostics.Debug.WriteLine("Error: " + ex.Message);
}
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(someURI);
HttpResponseMessage response = client.PostAsync(somePage, new StringContent(SerializeToJSON(events))).Result;
response.EnsureSuccessStatusCode();
}
If I don't make the call to the web server synchronous (with the '.Result'), it fails there. I've tried a lot of ways to get the data from the IObservable into something I can send, but either the code fails (usually with a bad cast of some sort), or the events are not yet put into the data structure that I want to send. I know that RX is by nature async, and I'm asking to deal with it in a synchronous way, I would figure that there would be a solution. Thanks in advance!
Supposing that you control the Observable source, you could call Observable.OnComplete() like Enigmativity has pointed out. Otherwise, you could try to keep a copy of every value received before buffering it:
Observable.Do(x => localCopy = x).Buffer(..)
This local copy would be accessible to you at shutdown.
In any case, please note that .First() is marked obsolete in the latest Rx versions, possibly to avoid the problem you are experiencing.

FindNextPrinterChangeNotification misses events?

I am using FindFirstPrinterChangeNotification and FindNextPrinterChangeNotification to catch printing events. However I have noticed that FindNextPrinterChangeNotification does not reliably returns all the events. I have found a guy with the same problem in this article.
Basically, when I debug my program, or put Sleep command like his suggestion when processing an event, FindNextPrinterChangeNotificationskips a lot of events. Also, most of the time I get a lot of SPOOLING status events but miss the DELETED status event (sometimes I get it, but most of the time I cannot), even though I already push the jobs to a Queue for later processing.
Does anyone have this problem too? Also, I am trying the Microsoft PDF Printer, The NumberOfPages increases as the SPOOLING events come, but the NumberOfPagesPrinted does not. Is it intended?
EDIT After some investigation, the events are not actually gone. If I call another print job, the previous events are fired (including the DELETING/DELETED status of previous print job). Can you please suggest what is the problem?
Here's the code for calling FindFirstPrinterChangeNotification:
//We got a valid Printer handle. Let us register for change notification....
_changeHandle = FindFirstPrinterChangeNotification(_printerHandle, (int)PRINTER_CHANGES.PRINTER_CHANGE_JOB, 0, _notifyOptions);
// We have successfully registered for change notification. Let us capture the handle...
_mrEvent.SafeWaitHandle = new Microsoft.Win32.SafeHandles.SafeWaitHandle(_changeHandle, true);
//Now, let us wait for change notification from the printer queue....
_waitHandle = ThreadPool.RegisterWaitForSingleObject(_mrEvent, new WaitOrTimerCallback(PrinterNotifyWaitCallback), _mrEvent, -1, true);
And this is for the FindNextPrinterChangeNotification:
_notifyOptions.Count = 1;
_notifyOptions.dwFlags = PRINTER_NOTIFY_OPTIONS_REFRESH;
int pdwChange = 0;
IntPtr pNotifyInfo = IntPtr.Zero;
bool bResult = FindNextPrinterChangeNotification(_changeHandle, out pdwChange, _notifyOptions, out pNotifyInfo);
I had the same issue then I tried:
_waitHandle = ThreadPool.RegisterWaitForSingleObject(_mrEvent, new WaitOrTimerCallback(PrinterNotifyWaitCallback), _mrEvent, -1, true);
with:
_waitHandle = ThreadPool.RegisterWaitForSingleObject(_mrEvent, new WaitOrTimerCallback(PrinterNotifyWaitCallback), _mrEvent, -1, false);
(false arg in the end)
and seems to work now

Observable with Timer for specifc value

Not sure about the title of my question but hopefully I can explain what I am trying to do.
I want to have a Timer to inject a value into a sequence but when a specific value is observed.
I want the Timer to be cancelled when any other value is entered into the sequence.
public enum State
{
Connected,
Disconnected,
DisconnectedRetryTimeout
}
var stateSubject = new Subject<State>();
var connectionStream = stateSubject.AsObservable();
var disconnectTimer =
Observable.Return(State.DisconnectedRetryTimeout)
.Delay(TimeSpan.FromSeconds(30))
.Concat(Observable.Never<State>());
var disconnectSignal =
disconnectedTimer
.TakeUntil(connectionStream.Where(s => s == State.Connected))
.Repeat();
var statusObservable =
Observable.Merge(connectionStream, disconnectSignal)
.DistinctUntilChanged();
So when nothing is in the stream (i.e. new) no timer.
When Connected|DisconnectedRetryTimeout is add no timer.
When Disconnected is add I want the timer to start
If Connected is on the stream before the timer fires I want the timer cancelled
The Timer should only fire once, until Disconnected is received again.
Pretty new to RX and ran out of ideas on this one.
Any help much appreciated.
If I understand the problem correctly: We start with a state stream that will emit either Connected or Disconnected messages. We want to enrich this with DisconnectedRetryTimeout message that appears if a Disconnected message sits on the stream for 30 seconds without a Connected message appearing.
One way to do this has the following idea:
Project the Connected/Disconnected stream into the DisconnectedRetryTimeout stream as follows:
First strip duplicates with DistinctUntilChanged as we only want the first Disconnected message of a batch to start a timer.
If Disconnected is received, project this event as a stream that emits DisconnectedRetryTimeout after 30 seconds
If Connected is received, just project an infinite and empty stream (Observable.Never)
With the above, we end up with a stream of streams, so now we use Switch which flattens this by always taking the most recent stream. So if Connect appears whilst the timer is in flight, the Never stream will replace the timer stream.
Now we can merge this with the original de-duped stream. Note that we publish the de-duped stream because we will be subscribing to it twice - if we don't do this, and the source is cold then we can run into problems. See more about that here.
var stateSubject = new Subject<State>();
var state = stateSubject.DistinctUntilChanged().Publish().RefCount();
var disconnectTimer = state
.Select(x => x == State.Disconnected
? Observable.Timer(TimeSpan.FromSeconds(30))
.Select(_ => State.DisconnectedRetryTimeout)
: Observable.Never<State>())
.Switch();
var statusObservable =
state.Merge(disconnectTimer);
EDIT: Simpler Version
You can do this all in one go and drop the publish step and merge - by using StartWith we can push the Disconnected events through the timer stream, and with Observable.Return we can push the Connected through replacing the empty Never stream:
var statusObservable = stateSubject
.DistinctUntilChanged()
.Select(x => x == State.Disconnected
? Observable.Timer(TimeSpan.FromSeconds(5))
.Select(_ => State.DisconnectedRetryTimeout)
.StartWith(State.Disconnected)
: Observable.Return(State.Connected))
.Switch();

Fail Fast with WebClient

Using a modified WebClient, I download data periodically from a service with the following characteristics:
The data download (~1GB) can take around 20 minutes
Sometimes the service decides not to return any data at all (request hangs), or takes minutes to hours to return the first byte.
I would like to fail fast in the event that the service does not return any data within a reasonable (configurable) amount of time, yet allow plenty of time for a download that is making progress to succeed.
It seems that the WebRequest.Timeout property controls the total time for the request to complete, while ReadWriteTimeout controls the total time available to read data once the data transfer begins.
Am I missing a property that would control the maximum amount of time to wait between establishing the connection and the first byte returning? If there is no such property, how can I approach the problem?
I am not aware of any additional timeout property that will achieve the result you are looking for. The first thought that comes to mind is attaching a handler to DownloadProgressChanged that will update a flag to indicate data has been received (not always accurate though).
Using a Timer or EventWaitHandle you could then block (or handle async if you prefer) for a short period of time and evaluate whether any data has been received. The code below is not a fully fleshed out example, but an idea of how it may be implemented.
using (var manualResetEvent = new ManualResetEvent(false))
using (var client = new WebClient())
{
client.DownloadProgressChanged += (sender, e) => manualResetEvent.Set();
client.DownloadDataAsync(new Uri("https://github.com/downloads/cbaxter/Harvester/Harvester.msi"));
if (!manualResetEvent.WaitOne(5000))
client.CancelAsync();
}
In the above example, the manualResetEvent.WaitOne will return true if DownloadProgressChanged was invoked. You will likely want to check e.BytesReceived > 0 and only set for non-zero values, but I think you get the idea?

Categories