How to detect SerialDataReceivedEvent Args when while loop is still ongoing? - wpf

I created a program combining scanner (using comport) and weight, and I want to escape a while loop when another data is received from SerialDataReceivedEventArgs.
I have write this code to handle the data:
private void DataReceivedHandler(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
dataScanned = sp.ReadLine();
dataScanned = dataScanned.Trim();
}
How to detect when another Scan is being done?
Edit:
As mentioned by #Ozgur Saklanmaz I want the DataReceived interrupt to be triggered if new data is triggered, delete the previous data and process the new data immediately.
Thank you for answering.

Related

Flink - Need way to notify one stream from another

I have an Apache flink usecase that works as follows:
I have data events coming in through first stream. Part of each event is a foreign key for which I expect data from the second stream. E.g.: I am getting data for major cities in the first stream which has a city-code and I need the average temperature over time for this city code streamed through the second stream. It is not possible to have temperatures streamed for all possible cities, we have to request the city for which we need the data.
So we need some way to "notify" the second stream source that we need data for this city "pushed" when we encounter it the first time in the first stream.
This would have been easy if this notification could be done from the first stream. The problem is that the second stream is coming to us through a websocket part of which is a control channel through which we have to make the request - so the request HAS to be made from the second stream.
Check event in the first stream. Read city code x.
Have we seen this city code? If not, notify the second stream, we need data for city code x.
Second stream sends message to source for data for x.
Data starts flowing in for city x, which is used to join downstream.
If notification from the first stream was possible, this would be easy - I could have done it from step 2, so data starts flowing in the second stream. But that is not possible as the request needs to be send on the same websocket connection that feeds the second stream.
I have explored using CoProcessFunction or RichCoMapFunction for this - but it is not clear how this can be done. I have seen some examples of Broadcast State Pattern - but even that does not seem to fit the usecase.
Can someone help me with some pointers on possible solutions?
So I made it work using the suggestion of the side output stream. Thanks #whatisinthename and #kkrugler for the suggestions.
Still trying to figure out details, but here's a summary
From the notification stream (stream 1), create a side output stream (stream 1-1).
Use an extended class (TempRequester) of KeyedProcessFunction, to process the side output stream 1-1 and create Stream 2 from it. The KeyedProcessFunction has the websocket connection.
In the open method of the KeyedProcessFunction create the connection to websocket (handshaking etc.). Have a ListState state to keep the list of city codes.
In the processElement function of TempRequester, check the city code coming in from side output stream 1-1. If present in ListState, do nothing. Else, send a message through websocket control channel and request city data and add the code to ListState. Create a process timer (this is one time) to fire after 500 milliseconds or so. The websocket server writes the temp data very frequently and that is saved in a queue.
In the onTimer method, check the queue, read the data and push out (out.collect...). Create a timer again. So essentially, once the first city code gets in, we create a timer that runs every 500 milliseconds and dumps the records received out into the second stream.
Now the first and second streams can be joined downstream (I used the table API).
Not sure if this is the most elegant solution, but it worked. Thanks for the suggestions.
Here's the approximate main code:
DataStream<Event> notificationStream =
env.addSource(this.notificationSource)
.returns(TypeInformation.of(Event.class));
notificationStream.assignTimestampsAndWatermarks(WatermarkStrategy.forMonotonousTimestamps());
final OutputTag<String> outputTag = new OutputTag<String>("cities-seen"){};
SingleOutputStreamOperator<Event> mainDataStream = notificationStream.process(new ProcessFunction<Event, Event>() {
#Override
public void processElement(
Event value,
Context ctx,
Collector<Event> out) throws Exception {
// emit data to regular output
out.collect(value);
// emit data to side output
ctx.output(outputTag, event.cityCode);
}
});
DataStream<String> sideOutputStream = mainDataStream.getSideOutput(outputTag);
DataStream<TemperatureData> temperatureStream = sideOutputStream
.keyBy(value -> value)
.process(new TempRequester());
temperatureStream.assignTimestampsAndWatermarks(WatermarkStrategy.forMonotonousTimestamps());
// set up the Java Table API and rest of SQL based joins ...
And the approximate code for TempRequester (ProcessFunction):
public static class TempRequester extends KeyedProcessFunction<String, String, TemperatureData> {
private ListState<String> allCities;
private volatile boolean running = true;
//This is the queue for requesting city codes
private BlockingQueue<String> messagesToSend = new ArrayBlockingQueue<>(100);
//This is the queue for receiving temperature data
private ConcurrentLinkedQueue<TemperatureData> messages = new ConcurrentLinkedQueue<TemperatureData>();
private static final int TIMEOUT = 500;
#Override
public void open(Configuration parameters) throws Exception {
super.open(parameters);
allCities = getRuntimeContext().getListState(new ListStateDescriptor<>("List of cities seen", String.class));
... rest of websocket client setup code ...
}
#Override
public void close() throws Exception {
running = false;
super.close();
}
private boolean initialized = false;
#Override
public void processElement(String cityCode, Context ctx, Collector<TemperatureData> collector) throws Exception {
boolean citycodeFound = StreamSupport.stream(allCities.get().spliterator(), false)
.anyMatch(s -> cityCode.equals(s));
if (!citycodeFound) {
allCities.add(cityCode);
messagesToSend.put(.. add city code ..);
if (!initialized) {
ctx.timerService().registerProcessingTimeTimer(ctx.timestamp()+ TIMEOUT);
initialized = true;
}
}
}
#Override
public void onTimer(long timestamp, OnTimerContext ctx, Collector<TemperatureData> out) throws Exception {
TemperatureData p;
while ((p = messages.poll()) != null) {
out.collect(p);
}
ctx.timerService().registerProcessingTimeTimer(ctx.timestamp() + TIMEOUT);
}
}

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.

WPF - How to model a loop operation in the UI

I am creating a quick'n'dirty utility that will enable editing of data read sequentially from a set of files. Here's a very simplified explanation of what will happen in a single iteration of a loop:
Read a line from the input stream
Parse it and use the parsed results to populate form controls
Allow user editing and await a confirmation button click
Retrieve the updated form control values and write to the output stream
What I can't figure out is how to integrate the processing loop with the event-driven UI. For example, how do I suspend operation of the loop while waiting for user input.
I understand that this is possible by launching the loop operation on its own thread and writing code to manage its interaction with the UI thread, but I am wondering if there is a simpler approach that works out of the box.
Thanks for any ideas you may be able to offer.
Tim
I can think of 2 approaches to do that:
The easiest is probably to use a modal dialog: when your worker thread needs input from the user, display a dialog, which is a blocking operation. Something like that:
// Worker thread loop
while(...)
{
...
// prompt user for data (invoke synchronously on UI thread)
UserData data = (UserData)window.Invoke(PromptUserData);
...
}
...
UserData PromptUserData()
{
UserInputDialog dlg = new UserInputDialog();
dlg.ShowDialog();
return dlg.UserData;
}
The other option, if you don't want to use a modal dialog, is to use a wait handle to synchronize the worker thread and the UI:
private readonly AutoResetWaitHandle _userInputWaitHandle = new AutoResetWaitHandle(false);
...
// Worker thread loop
while(...)
{
...
// Setup the UI to allow user input
window.Invoke(SetupUIForInput);
// Wait for the input to be validated
_userInputWaitHandle.WaitOne();
...
}
...
void SetupUIForInput()
{
// Enable the UI
inputForm.Enabled = true;
// Whatever else you need to do...
...
}
void buttonOK_Click(object sender, EventArgs e)
{
// Signal the worker thread to continue
_userInputWaitHandle.Set();
}
You wouldn't really implement a loop in the narrow sense.
You would do something like this (pseudo code):
OnStartOperationButtonClick()
{
if(!ReadLine())
return;
ParseLineAndPopulateControls();
ShowEditingControls();
}
OnConfirmationButtonClick()
{
GetControlValuesAndWriteToOutputStream();
if(!ReadLine())
{
HideEditingControls();
return;
}
ParseLineAndPopulateControls();
}
No need for a separate thread, given that reading and parsing the line doesn't take long.

Complex multi-threaded interface

First of all its not a splash-screen what i want... just to be clear... ok... lets go to the description of the problem:
i have a form that fire N number of threads (i dont know how many, the user must choose)... each thread has a object, and during several moments the objects may fire a event to signal some change... there must be a form for each thread to "report" the messages that the events are sending...
my problem is: the threads create the forms perfectally... but the desappear... out of nowhere... they appear on the screen... and vanish... poof.... gone! how can i avoid that undesired "disposing"?!?!
Your threads must either
use proper InvokeRequired + Invoke logic
or run their own MessagePump (Application.Run)
Which one did you (not) do?
If you create a form in a thread, the form will vanish when the thread is done. If you want the form to survive longer than that you need to either keep the thread alive, or create the form on the application's main thread. The latter would be preferable. Just make sure that each to hook up event listener for the object in the corresponding form, and use Invoke or BeginInvoke as needed when updating the form.
A simple example:
First a worker:
class Worker
{
public event EventHandler SomethingHappened;
protected void OnSomethingHappened(EventArgs e)
{
var evnt = SomethingHappened;
if (evnt != null)
{
evnt(this, e);
}
}
public void Work()
{
// do lots of work, occasionally calling
// OnSomethingHappened
}
}
Then, in a form we have an event handler for the SomethingHappened event:
public void SomethingHappenedHandler(object sender, EventArgs e)
{
if (this.InvokeRequired)
{
this.Invoke(new Action(() => SomethingHappenedHandler(sender, e)));
return;
}
// update gui here
}
Then it's really just a matter of wiring it all together:
Worker w = new Worker();
ProgressForm f = new ProgressForm;
w.SomethingHappened += f.SomethingHappenedHandler;
f.Show();
Thread t = new Thread(w.Work);
t.Start();
Disclaimer: this sample is quickly tossed together and somewhat untested (sitting on the train, about to get off ;) ).
A Form must be hosted on a thread with a message loop. You can create a message loop by either calling Application.Run or Form.ShowDialog. However, unless you have really good reason for doing so I would avoid having more than one thread with a windows message loop.
I would also avoid creating N threads. There are better ways to parallelize N operations other than creating one thread per operation. To name only two: 1) queue a work item in the ThreadPool or 2) use the Task Parallel Library via the Task class. The problem with creating N threads is that each thread consumes a certain amount of resources. More threads means more resources will be consumed and more context switching will occur. More is not always better in the world of multithreading.

Update Label while processing in Windows Forms

What is the best way to update a label on a Windows Forms application while processing?
I have a loop that does some processing to files on the user's system when the user clicks a button.
foreach (System.IO.FileInfo f in dir.GetFiles("*.txt"))
{
// Do processing
// Show progress bar
// Update Label on Form, "f.Name is done processing, now processing..."
}
What would be some sample code?
What exactly is this called? Is it threading or delegates?
A quick fix for you would be:
Label1.Text = f.Name + " is done processing, now processing...";
Label1.Refresh();
You really want to avoid DoEvents, otherwise you'll have problems if your user repeatedly presses buttons on your form.
You should be doing this on another thread, and then updating your UI thread from that thread. You are blocking further processing by performing this work on the UI thread.
If you can't move this code to the UI thread, then you could always call Application.DoEvents, but I strongly suggest you explore these options first:
System.ComponentModel.BackgroundWorker
System.Threading.ThreadPool
System.Threading.Thread
System.Threading.Tasks namespace
You'll need to get your data from one thread to the other. This can be done in a couple of ways...
First, your "background" thread could update some kind of "CurrentStatus" string variable that it changes as it goes along. You could then put a timer on your form that would then grab the CurrentStatus variable and update the label with it.
Second, you could simply invoke the operation from the background thread to the UI thread with a delegate using the InvokeRequired property of the label control. So for example...
private delegate void UpdateStatusDelegate(string status);
private void UpdateStatus(string status)
{
if (this.label1.InvokeRequired)
{
this.Invoke(new UpdateStatusDelegate(this.UpdateStatus), new object[] { status });
return;
}
this.label1.Text = status;
}
You can call that UpdateStatus() method from any thread (UI or background), and it will detect whether or not it needs to invoke the operation on the main UI thread (and if so, does it).
To actually set up the thread, you can do so like this:
private void StartProcessing()
{
System.Threading.Thread procThread = new System.Threading.Thread(this.Process);
procThread.Start();
}
private void Process() // This is the actual method of the thread
{
foreach (System.IO.FileInfo f in dir.GetFiles("*.txt"))
{
// Do processing
// Show progress bar
// Update Label on Form, "f.Name is done processing, now processing..."
UpdateStatus("Processing " + f.Name + "...");
}
}
Then when the user clicks the "GO" button you'll simply call StartProcessing().
If your processing is lengthy do it in a backgroundworker thread.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
I also recommend to use :
Application.DoEvents();
Processes all Windows messages currently in the message queue.

Resources