i'm developping an app that use a GPS connected to the port com of my computer.
My application get 2 Windows, the first one is a display window, i will show all my GPS datas and the second one is a Map.
I have put all my code for opening the COM port and read it in the App.cs
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
using tmagpsapi;
namespace TDF
{
public partial class App : Application
{
private tmagpsapi.NMEA gps;
private tmaSerialport sp;
private void Application_Startup(object sender, StartupEventArgs e)
{
gps = new NMEA();
sp = new tmaSerialport();
sp.ComPortOpen += new tmaSerialport.ComPortOpenEventHandler(comportOpen);
sp.ComPortError += new tmaSerialport.ComPortErrorEventHandler(comportError);
sp.ComPortClosed += new tmaSerialport.ComPortClosedEventHandler(comportClosed);
gps.SuccessfulFix += new NMEA.SuccessfulFixEventHandler(gpsSuccessFix);
sp.Openport(30, System.IO.Ports.Parity.None, tmagpsapi.tmaSerialport.enumDatabits.Bit8, System.IO.Ports.StopBits.One, tmagpsapi.tmaSerialport.enumBaudRates.BaudRate9600);
sp.LineRecieved += sp_LineRecieved;
}
void sp_LineRecieved(string Data)
{
try
{
if (this.MainWindow != null)
{
var currentWindow = this.MainWindow as GPSWindow;
currentWindow.GPSHandle(Data);
}
else
{
System.Windows.Forms.MessageBox.Show("NULL");
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
System.Windows.Forms.MessageBox.Show(e.Message);
}
}
private void comportClosed()
{
Console.WriteLine("COM PORT CLOSED");
System.Windows.Forms.MessageBox.Show("COM PORT CLOSED");
}
private void comportError(System.Exception es, String message)
{
Console.WriteLine("Error : " + message);
System.Windows.Forms.MessageBox.Show("Error : " + message);
}
private void comportOpen() {
Console.WriteLine("COM PORT OPENED");
System.Windows.Forms.MessageBox.Show("COM PORT OPENED");
}
private void gpsSuccessFix(tmagpsapi.NMEA_Position position)
{
Console.WriteLine("GPS OK");
System.Windows.Forms.MessageBox.Show("GPS OK");
}
private void Application_Exit(object sender, ExitEventArgs e)
{
sp.Close();
}
}}
As you can see in this code, when i start the app, i open my COM Port and when i close the app i closed it.
When i have a new data on my COM Port the function sp_LineRecieved is called.
In this function i want to send those data to my currentWindow opened. To do that i have create an interface named "GPSWindow" (with one method void GPSHandle(string data))
But when I try to call the currentWindow.GPSHandle(Data) i got an error on my catch : "The calling thread cannot access this object because a different thread owns it".
I have try to use the Application.Current.Dispatcher but every thing i tried send me this result.
Maybe i can pass those data with an event handler but i don't know how to do it.
My Question is:
How can I access a thread which is already used by a different thread ?
void GPSWindow.GPSHandle(string data)
{
System.Windows.Forms.MessageBox.Show("GPS : " + data);
}
Try this
1 ) Add the folowing event handller in App class
public static event EventHandler<String> RaiseWhenANewLineRecieved = delegate {};
2 ) When a new line received add the following
RaiseWhenANewLineRecieved(this, Data);
3) Add the event listener in the MainWindow's constructor
App.RaiseWhenANewLineRecieved += App_RaiseWhenANewLineRecieved;
4) Show the data in the MainWindow
void App_RaiseWhenANewLineRecieved(object sender, string e)
{
System.Windows.Forms.MessageBox.Show("GPS : " + e);
}
Related
I'm trying to implement a SCS framework server with WinForms in C# but I am having issues making it work. The server standalone works fine when using it in the Main method (no WinForms). I have a client-sided and a server-sided sample code from the SCS framework that I'm trying to implement in WinForms together with some of my own code. It all went well until I decided to try and use WinForms aswell (I had to move the server code to a class of it's own).
I am not getting any errors when I am starting the server, however I can't connect with the client anymore (worked before I moved the server to a class of its own). Client gets System.Net.Sockets.SocketException. On the server-side, I get the error System.InvalidOperationException when the client is trying to connect.
This is my Form1.cs:
using System;
using System.Windows.Forms;
namespace Server_Test
{
public partial class Form1 : Form
{
public static Form1 Self;
Server server = new Server();
public Form1()
{
InitializeComponent();
Self = this;
}
public void rtb1Text(string text)
{
richTextBox1.AppendText(text);
}
public void rtb2Text(string text)
{
richTextBox2.Text = text;
}
private void button1_Click(object sender, EventArgs e)
{
if (button1.Text.EndsWith("Start"))
{
button1.Text = "Stop";
server.ServerInit();
}
else if (button1.Text.EndsWith("Stop"))
{
button1.Text = "Start";
// Does nothing atm
}
}
}
}
And this is my Server.cs
using System;
using Hik.Communication.Scs.Communication.EndPoints.Tcp;
using Hik.Communication.Scs.Communication.Messages;
using Hik.Communication.Scs.Server;
namespace Server_Test
{
class Server
{
public void ServerInit()
{
// Create a server that listens 10085 TCP port for incoming connections
var server = ScsServerFactory.CreateServer(new ScsTcpEndPoint(10085));
// Register events of the server to be informed about clients
server.ClientConnected += Server_ClientConnected;
server.ClientDisconnected += Server_ClientDisconnected;
// Start the server
server.Start();
// Form1.Self.rtb1Text("Server has been started successfully.\n");
Console.WriteLine("Server has been started successfully.\n");
}
static void Server_ClientConnected(object sender, ServerClientEventArgs e)
{
Form1.Self.rtb1Text("A new client with ID: " + e.Client.ClientId + " has connected.\n");
// Register to MessageReceived event to receive messages from new client
e.Client.MessageReceived += Client_MessageReceived;
}
static void Server_ClientDisconnected(object sender, ServerClientEventArgs e)
{
Form1.Self.rtb1Text("A client is disconnected! Client Id = " + e.Client.ClientId + "\n");
}
static async void Client_MessageReceived(object sender, MessageEventArgs e)
{
var message = e.Message as ScsTextMessage; // Server only accepts text messages
if (message == null)
{
return;
}
//Get a reference to the client
var client = (IScsServerClient)sender;
Form1.Self.rtb1Text("Client (ID:" + client.ClientId + ") sent a request: " + message.Text + "\n");
switch (message.Text)
{
case "api":
HttpPost httpPost = new HttpPost();
var apiResponse = await httpPost.SendPost("robot_info");
//Send reply message to the client
client.SendMessage(
new ScsTextMessage(
apiResponse,
message.MessageId //Set first message's id as replied message id
));
break;
default:
break;
}
}
}
}
My guess is that I'm doing something wrong when creating a new instance of the Server class and how I'm initializing/starting the server. Might be something else though, I've tried debugging but it didn't make me any smarter.
Any ideas?
The code i have works, but i want to make sure it's robust, as i remember writing similar code in the past (with python) and noticing that i was receiving datas that would be 3 or 4 minutes old and would get even older with time.
I guess this has to do with the serial buffer, and that i should "clear it" from time to time, what is the best practice for this ?
C# form code:
using System;
using System.Windows.Forms;
using System.IO.Ports;
namespace SerialTest1
{
public partial class Form1 : Form
{
public SerialPort ArduinoSerial;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Timer MyTimer = new Timer();
MyTimer.Interval = (1000); // 1 sec
MyTimer.Tick += new EventHandler(SerialTimer_Tick);
MyTimer.Start();
Console.WriteLine("Form1_Loading....");
OpenSerialPort();
}
private void OpenSerialPort() // creating serial communication object
{
try
{
Console.WriteLine("OpenSerialPort: opening port.....");
ArduinoSerial = new SerialPort("COM7", 115200);//Set board COM
ArduinoSerial.Open();
ArduinoSerial.DataReceived += new SerialDataReceivedEventHandler(dataReceived);
}
catch (Exception ex)
{
Console.WriteLine("OpenSerialPort: Can not find port");
}
}
// write to arduino and restart Serial com if error like cable disconnected and reconnected
private void writeToArduino()
{
try
{
Console.WriteLine($"writeToArduino: writing msg to arduino");
ArduinoSerial.WriteLine("hello from pc");
}
catch (Exception ex)
{
Console.WriteLine("writeToArduino: Serial Error");
//MessageBox.Show("Serial Error: " + ex.ToString(), "ERROR");
if (!ArduinoSerial.IsOpen)
{
Console.WriteLine("writeToArduino: ArduinoSerial is close, opening it...");
OpenSerialPort();
}
}
}
private void SerialTimer_Tick(object sender, EventArgs e) // will write to arduino at each timer tick
{
writeToArduino();
}
private void dataReceived(object sender, SerialDataReceivedEventArgs e) // receiving datas from arduino
{
string SerialLine = ArduinoSerial.ReadLine();
Console.WriteLine($"dataReceived: Got serial line for arduino: {SerialLine}");
}
}
}
Arduino code:
#include <TimeLib.h>
#include <Time.h>
//WINDOWS COMMUNICATION
String receivedString;
void setup(void) {
Serial.begin(115200);
}
void loop(void) {
static time_t lastMsg = 0;
static int counter = 1;
if (now() - lastMsg > 1) {
lastMsg = now();
Serial.print("msg ");
Serial.print(counter);
Serial.println("Hello from arduino");
counter++;
}
while (Serial.available() > 0) {
receivedString = Serial.readString();
Serial.println(receivedString);
}
delay(5);
}
I write code to create and connect to VPN using Dotras in C#. It works very good, but when I write code to get connection status, It doesn't work.
I read Dotras document, and write code like example, but It still doesn't work.
It doesn't show status in multiple line textbox. :(
Please show me, what I wrong. Thank you.
Here is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DotRas;
using System.Net;
namespace VPN1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btn_create_vpn_Click(object sender, EventArgs e)
{
try
{
string vpnuser = txt_vpn_user.Text;
string ip_address = txt_IP.Text;
this.rasPhoneBook1.Open();
RasEntry entry = RasEntry.CreateVpnEntry(vpnuser, ip_address, RasVpnStrategy.Default, RasDevice.GetDeviceByName("(PPTP)", RasDeviceType.Vpn, false));
this.rasPhoneBook1.Entries.Add(entry);
MessageBox.Show("Success");
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private RasHandle handle = null;
private void btn_dial_Click(object sender, EventArgs e)
{
this.rasDialer1.EntryName = txt_vpn_user.Text;
string username = txt_user.Text;
string password = txt_pass.Text;
this.rasDialer1.PhoneBookPath = RasPhoneBook.GetPhoneBookPath(RasPhoneBookType.AllUsers);
try
{
this.rasDialer1.Credentials = new NetworkCredential(username, password);
this.handle = this.rasDialer1.DialAsync();
this.btn_disconnect.Enabled = true;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void rasDialer1_StateChanged(object sender, StateChangedEventArgs e)
{
this.txt_status.AppendText(e.State.ToString() + "\r\n");
}
private void rasDialer1_DialCompleted(object sender, DialCompletedEventArgs e)
{
if(e.Cancelled)
{
this.txt_status.AppendText("Cancelled");
}
else if(e.TimedOut)
{
this.txt_status.AppendText("Timeout");
}
else if(e.Connected)
{
this.txt_status.AppendText("Connection successful");
}
else if (e.Error != null)
{
this.txt_status.AppendText(e.Error.ToString());
}
if(!e.Connected)
{
this.btn_disconnect.Enabled = false;
}
}
private void btn_disconnect_Click(object sender, EventArgs e)
{
if(this.rasDialer1.IsBusy)
{
this.rasDialer1.DialAsyncCancel();
}
else
{
RasConnection connection = RasConnection.GetActiveConnectionByHandle(this.handle);
if(connection!=null)
{
connection.HangUp();
}
}
}
}
}
If the events are not firing, the issue might be that the Events are not set in the events section in the properties window of the rasDialer1 control you added to the form (Form1). Using Visual Studio, Enter the design view, click on the rasDialer1 control which reveals the properties of the RasDialer you added, then navigate to events section (marked with a lightening icon) and then set the StateChanged and DialCompleted events.
OR
You can do all this from code simply by
rasDialer.StateChanged += rasDialer1_StateChanged;
rasDialer.DialCompleted += rasDialer1_DialCompleted;
somewhere in the Form1() constructor, where rasDialer1_StateChanged and rasDialer1_DialCompleted are the event handlers in your code.
I'm also anticipating a potential error within your code where accessing UI controls in those event handlers will get you a Cross-thread operation not valid error since they are called from an async operation this.rasDialer1.DialAsync();
The right way of accessing controls from methods called from another thread is below ...
textbox1.Invoke(new Action(() => textbox1.text = "my string"));
Try using dial instead of dialAsync
try:
{
File.WriteAllText("your rasphone.pbk path","")//Add
string vpnuser = txt_vpn_user.Text;
string ip_address = txt_IP.Text;
this.rasPhoneBook1.Open();
RasEntry entry = RasEntry.CreateVpnEntry(vpnuser, ip_address, RasVpnStrategy.Default, RasDevice.GetDeviceByName("(PPTP)", RasDeviceType.Vpn, false));
this.rasPhoneBook1.Entries.Add(entry);
MessageBox.Show("Success");
}
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 6 years ago.
In the below code, I am getting null reference exception I didn't understand why I am getting that. Please help me to solve it.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Data.SqlClient;
using System.Configuration;
namespace TCPListener
{
public partial class Form1 : Form
{
// Declare our worker thread
private Thread workerThread = null;
public Form1()
{
InitializeComponent();
// Initialise and start worker thread
this.workerThread = new Thread(new ThreadStart(this.ReceiveTcpData));
this.workerThread.Start();
}
public void timer1_Tick(object sender, EventArgs e)
{
}
public TcpListener server = null;
public Int32 port = Convert.ToInt32(ConfigurationManager.AppSettings["PUERTO"].ToString());
public IPAddress localAddr = IPAddress.Parse(ConfigurationManager.AppSettings["IP"].ToString());
public void OpenSocket()
{
try
{
// TcpListener server = new TcpListener(port);
server = new TcpListener(localAddr, port);
// Start listening for client requests.
server.Start();
}
catch (SocketException e)
{
Common.CommonControls.writeToLogFile("SOCKET ERROR: " + e.Message);
}
finally
{
Common.CommonControls.writeToLogFile("INICIO DE ESCUCHA EN " + DateTime.Now);
}
}
private void ReceiveTcpData()
{
//Instancio los objetos
Entities.Program oPosiciones = new Entities.Program();
DataAccess.Program oPosicionesDA = new DataAccess.Program();
try
{
// Buffer for reading data
Byte[] bytes = new Byte[256];
String data = null;
// Enter the listening loop.
// Perform a blocking call to accept requests.
// You could also user server.AcceptSocket() here.
//TcpClient client = server.AcceptTcpClient();
TcpClient cliente = new TcpClient();
try
{
cliente = server.AcceptTcpClient();
}
catch (Exception e) { MessageBox.Show(e.ToString()); }
data = null;
// Get a stream object for reading and writing
NetworkStream stream = cliente.GetStream();
int i;
// Loop to receive all the data sent by the client.
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
// Translate data bytes to a ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
// Process the data sent by the client.
data = data.ToUpper();
if (data.Substring(0, 2) == "##")
{
//SalidaMonitor("Paquete recibido: LOGON REQUEST del equipo");
cliente.Close();
this.workerThread.Interrupt();
return;
}
byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);
//Show data on monitor
SalidaMonitor("Paquete recibido " + DateTime.Now + ": " + data);
//Declare entities
oPosiciones.Paquete = data;
//Database action
oPosicionesDA.InsertarPosiciones(oPosiciones);
// Send back a response.
//stream.Write(msg, 0, msg.Length);
//SalidaMonitor("Paquete enviado: " + msg);
}
// Shutdown and end connection
cliente.Close();
}
catch (SocketException e)
{
Common.CommonControls.writeToLogFile("SOCKET ERROR: " + e.Message);
}
catch (SqlException x)
{
Common.CommonControls.writeToLogFile("SQL ERROR: " + x.Message);
}
catch (Exception y)
{
Common.CommonControls.writeToLogFile("ERROR: " + y.Message);
}
finally
{
oPosiciones = null;
oPosicionesDA = null;
this.workerThread.Interrupt();
}
}
private void SalidaMonitor(string data)
{
lstMensajes.Invoke(new MethodInvoker(delegate { lstMensajes.Items.Add(data.ToString()); }));
lstMensajes.Invoke(new MethodInvoker(delegate { lstMensajes.SelectedIndex = lstMensajes.Items.Count - 1; lstMensajes.SelectedIndex = -1; }));
}
private void Form1_Load(object sender, EventArgs e)
{
OpenSocket();
}
private void Form1_Close(object sender, FormClosingEventArgs e)
{
server.Stop();
}
}
}
In the above code, I am getting error at cliente = server.AcceptTcpClient();. I don't understand why it's happening. If you need any information, let me know. Thanks
The Problem
in the constructor of the form you are creating and starting new Thread.
and this thread will call the ReceiveTcpData method, which user the server variable (and at this point this variable was not initialized yet) WHY??
because the server variable is initialized in the Form_Load which call the OpenSocket method to initalize the server variable. The most important part is The Form_Load method is called AFTER the constructor of the form.
In other words, the Thread is using the server variable before you initialize it.
The Solution
use the following constructor, and remove the Form_Load event handler
public Form1()
{
InitializeComponent();
// add this line.
OpenSocket();
// Initialise and start worker thread
this.workerThread = new Thread(new ThreadStart(this.ReceiveTcpData));
this.workerThread.Start();
}
Update
For the person who prefer to do everything in the Form_Load
here is another solution
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// add this line.
OpenSocket();
// Initialise and start worker thread
this.workerThread = new Thread(new ThreadStart(this.ReceiveTcpData));
this.workerThread.Start();
}
Well, if it is in that line, it is because server is not initialized.
i am working to make a c# program that can start streaming webcam, close and capture the still image when closing.
the programs work as excepted on my development machine but when i open it on other it dosent work and gives me unhandled exception: Afroge.Video.DirectShow error.
I have added references AFroge.Video.dll and AFroge.Video.DirectShow.dll
here is the exe file and code of my project.
sendspace .com/file/4okqsi
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
//Create using directives for easier access of AForge library's methods
using AForge.Video;
using AForge.Video.DirectShow;
namespace aforgeWebcamTutorial
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//Create webcam object
VideoCaptureDevice videoSource;
private void Form1_Load(object sender, EventArgs e)
{
}
void videoSource_NewFrame(object sender, AForge.Video.NewFrameEventArgs eventArgs)
{
//Cast the frame as Bitmap object and don't forget to use ".Clone()" otherwise
//you'll probably get access violation exceptions
pictureBoxVideo.BackgroundImage = (Bitmap)eventArgs.Frame.Clone();
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
//Stop and free the webcam object if application is closing
if (videoSource != null && videoSource.IsRunning)
{
videoSource.SignalToStop();
videoSource = null;
}
}
private void button1_Click(object sender, EventArgs e)
{
try {
if (videoSource.IsRunning)
{
videoSource.Stop();
pictureBoxVideo.BackgroundImage.Save("abc.png");
pictureBoxVideo.BackgroundImage = null;
}
}
catch (Exception er) { }
}
private void button2_Click(object sender, EventArgs e)
{
try {
//List all available video sources. (That can be webcams as well as tv cards, etc)
FilterInfoCollection videosources = new FilterInfoCollection(FilterCategory.VideoInputDevice);
//Check if atleast one video source is available
if (videosources != null)
{
//For example use first video device. You may check if this is your webcam.
videoSource = new VideoCaptureDevice(videosources[0].MonikerString);
try
{
//Check if the video device provides a list of supported resolutions
if (videoSource.VideoCapabilities.Length > 0)
{
string highestSolution = "0;0";
//Search for the highest resolution
for (int i = 0; i < videoSource.VideoCapabilities.Length; i++)
{
if (videoSource.VideoCapabilities[i].FrameSize.Width > Convert.ToInt32(highestSolution.Split(';')[0]))
highestSolution = videoSource.VideoCapabilities[i].FrameSize.Width.ToString() + ";" + i.ToString();
}
//Set the highest resolution as active
videoSource.VideoResolution = videoSource.VideoCapabilities[Convert.ToInt32(highestSolution.Split(';')[1])];
}
}
catch { }
//Create NewFrame event handler
//(This one triggers every time a new frame/image is captured
videoSource.NewFrame += new AForge.Video.NewFrameEventHandler(videoSource_NewFrame);
//Start recording
videoSource.Start();
}
}
catch (Exception er) { }
}
}
}
Try this link!
It worked for me!
If some parts cannot be installed. Delete all of the assemblies of AForge.Net and follow following tutorial.
https://premsivakumar.wordpress.com/2010/06/28/aforge-net-visual-studio-2010-setup-tutorial/