I'm writing a class which would handle all the serial communications with a external device (i.e. reading and writing). The data is being streamed to the computer at 20Hz, and occasionally data is also written to the device. The class would then output valid data through an event to the main UI.
I want to put this class in a separate thread because my previous code caused some 'stuttering' in the device since it was in the main UI thread.
I'm just unsure of how to structure and implement the SerialPort class with a thread/background worker because I'm inexperienced in this area.
Would only the data received event exist inside the thread/background worker?
How would you pass data in and out of the created thread/background worker?
Any hints or suggestions would be much appreciated!
My first tip is that you should think of it like it was network (Socket) communication. The threading issues are much the same. Looking thru the MSDN documentation they have (if I remember correctly) two different ways of doing this, async and sync. I personally would use one of the async ways.
You can also take a look at the new Task library.
Start looking in to that and come back if you have further questions =)
Also from the msdn library serial port with threading example this is to console, but anyway.
You just implement in another thread the actual use of the SerialPort. When the time comes to "notify" your UI, you use "BeginInvoke" to get the actual UI handling to run inside the UI thread.
Something like:
string s = _port.ReadLine();
form.BeginInvoke((MethodInvoker)delegate
{
_textbox.Text = s;
});
Just use the DataReceived event.
Related
I'm currently busy writing some c# code to interface with an Arduino. The code periodically samples audio and transmits data to physically represent the audio levels. I've created a WPF interface for this program, but I pretty much am at a dead end with the final steps. In my interface i would like to be able to change parameters for what is being transmitted as well as displaying feedback read from the COM port.
I don't really understand how to properly make threads in c# - I can imagine how you would create a separate process to manage the IO here as the COM port can only be operated on by a simple process. How would i simultaneously run a loop to sample my audio and send it and another loop to read the serial port, all while still remaining separated from the WPF process so the UI doesn't freeze.
Any tips about proper practice to create these threads securely and efficiently is massively appreciated too!
Thanks
The simplest model is to use a few separate Threads. Each thread runs in an infinite loop, which is defined in a method called a TreadProc, and so each Thread is like a seperate program, but it runs in the same Process and can interact directly with the UI.
These background threads can interact with the WPF UI through the UI Elements' dispatchers. See Threading Model - WPF
I have noticed that when the new thread is started from serialport Data received event that if the plan of execution includes just a few methods that may change some value and send on another port then it works fine, but if the method needs to do more extensive processing like sending on another port and waiting for ACK, send again and receiving decent sized amounts of data (20KB) in 256 byte packets then the thread just stops somewhere and never completes. When the code is stepped through it seems to work fine. I have read other topics of people asking about this issue but there was no "solution" just to use another method like timers to poll the ports instead. I even made a workaround by having the main thread "poll" a variable that is changed from the event rather then having the event do the work and this seems to work, but when using a windows form I had to create a new thread which seems to be doing the same thing and either not completing the code or not executing the new thread which is just a while look that runs forever checking a variable. I can provide code if needed just wanted some insight on how to address this properly.
Nobody here knew the answer to the questions or explained limitations, but i was able to get around the issues using timers to run while loops checking for variable changes and starting threads that did the same.
Im making a server for a new game proyect and im using C# (.NET Framework v4.5) for both client and server.
Im currently using something like this to manage my players.
new Thread(() =>
{
connection.ListenAndSend();
}).Start();
public void ListenAndSend()
{
while(working)
{
if(someThingToRead)
{
//Listening logic here
//Here i call my event for dataReceived with the data i just read.
}
else if (queue.Count > 0)
{
Send(queue.Dequeue().Data); //Send data from the Queue
}
}
The use of a Queue is because i should not access the stream from different threads (it throws InvalidOperationException i think) so i implemented the queue to send data from the same thread.
I think this is mostly OK but im worried about the events.
The events are firing and working fine but i have not tested yet with multiple clients so...
Is the event being executed in the same thread that the listener thread?
Could i have problems with fields being modified by multiple threads at the same time? (Im more experienced in java for example and i remember something about Syncronize interface?)
Its not done right now but later its possible that some event will end up calling the send method so adding data to the send Queue (But this should not be an issue right?)
This game will never be for a large number of players (probably between 2 and 8) if that matters.
Is there some serious problem im not seeing?
As im using the Queue im thinking it does not matter what thread do add the data but will my listening be stopped while it is doing the event code? (If its really on the same thread) and while that could not really be an issue will it be simultaneously accesing fields from multiple threads?
UPDATE:
Can i make all of this just with async/await?? i cant see how to make the listen loop that way but if its really possible please expand in an answer.
Also, this answer says the opposite.
UPDATE 2:
Now that i have tested my code and i know its working fine.
As pointed out in comments i could have done this using async/await with a lot less threads, but:
In which it would be better to use async/await instead of threads, keep in mind my game server should be able to take as much cpu/memory as needed and its fine if it does (Of course the threads are calling sleep when not doing job). And i would like my server to run the closer to real time as possible.
I also would like to point, the first time i made it to start processing my logic the serializing of the game map (around 60k objects) took around 600ms (and that will be for each client) so i ended up moving the serialize job to the socket thread.
With this in mind, who thinks it would be better to use Async/Await instead of new Threads
PD: Im only talking about my server, the game client is indeed using async/await to communicate with the server.
You have 2 options , ether lock the variable (which is not recommended)
How to lock a variable used in multiple threads
or use dispatcher for calling a method from another thread Using the C# Dispatcher
if you are not using WPF, you might take a look to this link : how do I convert wpf dispatcher to winforms
I currently have a console application written in Visual C# (2013). It opens up a connection to a USB Multimeter and then writes out the value to the console. I would now like to make this into a proper WinForms or WPF application (Data gets recieved, data gets sent to UI thread, data gets displayed in a table/graph etc). To do so, I need to receive the data on a seperate thread, as the data is sent through every 0.12ms (Which would lock up the UI on the main thread).
I have done some reading on both Threading and Async tasks, and as yet, have not decided which would be best suited to the task. Which of these (Or other methods) would be your method of choice for implementing this?
Please note, I am not asking people to write my code for me, I am simply asking which is the best method.
Asryael, your applications sounds fun. To beautify it you can create a WPF MVVM application.
It is not hard as it sounds.
Here is a basic tutorial:
http://www.codeproject.com/Articles/165368/WPF-MVVM-Quick-Start-Tutorial
The basic idea:
xaml -Defines the ui. Make it nice as you wish.
Then Have a variable in your xaml data bind to a property (variable)
update the variable in a thread everytime you get updates from your usb multimeter.
Have fun. Your application sounds like fun...
I have read dozens of articles about threading in c# and Application.DoEvents() ... Still can't use it properly to get my task done:
I have a controller connected to my COM, this controller works on command (i send command, need to wait few ms to get response from it), assume the response is a data that i want to plot every time interval using a loop:
start my loop.
send command to controller via serialPort.
wait for response (wait let say 20 ms).
obtain data.
repeat this loop every let say 100 ms.
this simply doesn't want to work!! i tried to communicate with the data controller on other thread but it seems that it can't access the serialPort which belongs to the main thread (roughly speaking).
any help is appreciated
Application.DoEvents is for all it does - nothing more than a nested call to a windows (low level) message loop on the same thread. Which might easily cause recursion if you call it in in an event handler. You might consider creating your serial port object on the worker thread and communicate through threading classes (i.e. the WaitHandles and similar). Or call back to your UI thread using "BeginInvoke" and "EndInvoke" on the UI object.
If you catch the SerialPort.DataReceived event and then use wither SerialPort.ReadLine or SerialPort.Read(byte[],int,int) those methods will be executed on a new thread. I prefer to use a mutex to control access to the buffer of bytes as a shared resource. Also have you ever communicated with your device successfully? If not in addition to the port setting check the SerialPort.NewLine property and the SerialPort.Handshake property. These settings vary depending on the device you are trying to communicate with.
Why do you use it to begin with?
Have a look at this pages, it might give you a direction
My favorite: Is DoEvents Evil?
From msdn blog Keeping your UI Responsive and the Dangers of Application.DoEvents
From msdn forums Application does not return from call to DoEvents
Without code, it'll be hard to help. Even with code, it might be hard to help :)
I'm agreeing with gunr2171 on this :)