named pipe client won't work in unity3d - c#

I wrote this C# code to have namedPipeServer and NamedPipeClient, with Asynchronous read and write settings, connect to each other. Both code runs perfectly on visual studio 2010 that I am using with read and write working well without any application freeze during runtime.
But I want the client side running in unity3d. The problem I encounter is in client side code implemented in Unity3D. When I use Write_to_Server_Async(string message), read in the server side is not invoked and is only invoked when I quit Unity3d (I have end its process typically). I can tell something wrong with Unity3D, because the exact code works perfectly in visual studio, so I know my code is implemented the right way. I have heard about how unity3d does not really use real threads unless user manually creates one but even that has not solved the problem. My speculation is Unity3D developers might have created their version of .NET library 3.5 (sounds bizzare (does explain why they still haven't adopted 4.5)) or somehow they must have structured their library in a way that by default functions like NamedPipeClientStream.BeginWrite cannot create its own real thread. But then again I am not sure if its the problem with threads.
At the moment, I would like anyone to come up with good explanation.
Make sure to replace Debug.WriteLine to UnityEngine.Debug.Log in unity3d.
Below is Client Main method code and class
class PipeClient
{
private static Asynchronus_NamedPipe_Client client;
static void Main(string[] args)
{
client = new Asynchronus_NamedPipe_Client("mypipe7055");
while (client.Is_connected_to_server()) {
if (Console.ReadKey().Key == ConsoleKey.T)
{
client.Write_to_Server_Async("NEX CLIENT");
}
}
}
}
Asynchronus_NamedPipe_Client class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Security.Principal;
using System.Diagnostics;
using System.Threading;
namespace NamedPipes_CLIENT
{
public class Asynchronus_NamedPipe_Client
{
public readonly string pipe_address;
private System.IO.Pipes.NamedPipeClientStream clientStream;
public bool filter_message = true;
private string Server_Message = null;
public event ASYNC_pipe_status_callback ASYNC_external_Write_Completed;
public event ASYNC_pipe_status_callback ASYNC_external_Read_Completed;
public delegate void ASYNC_pipe_status_callback(string message);
private byte[] read_buffer = new byte[1024];
private byte[] write_buffer = new byte[1024];
private IAsyncResult read_result;
private IAsyncResult write_result;
private int read_id = 1;
public Asynchronus_NamedPipe_Client(string pipe_address)
{
try
{
this.pipe_address = pipe_address;
// if(clientStream.IsConnected){UnityEngine.Debug.Log("Server Already Running");}else{}
clientStream = new NamedPipeClientStream(".", this.pipe_address, PipeDirection.InOut, PipeOptions.Asynchronous);
clientStream.Connect(1);
if (clientStream.IsConnected)
{
Console.WriteLine("Connected to Server");
Read_from_Server_Async();
}
else { Console.WriteLine("Could NOT connect to Server"); }
}
catch (Exception oEX) { Console.WriteLine("Application Pipe Error: "+oEX.Message); }
}
public void Write_to_Server_Async(string message)
{
if (clientStream != null)
{
if (clientStream.CanWrite && clientStream.IsConnected)
{
clientStream.WaitForPipeDrain();
ASCIIEncoding.ASCII.GetBytes(message).CopyTo(write_buffer,0);
clientStream.BeginWrite(write_buffer, 0, write_buffer.Length, new AsyncCallback(Async_Write_Completed), 1);
} else { close_pipe(); }
}
}
public void Read_from_Server_Async()
{
if (clientStream.CanRead && clientStream.IsConnected)
{
clientStream.BeginRead(read_buffer, 0, read_buffer.Length, new AsyncCallback(Async_Read_Completed), 2);
} else { close_pipe(); }
}
private void Async_Write_Completed(IAsyncResult result)
{
clientStream.EndWrite(result);
Debug.WriteLine("Written To Server => " + ASCIIEncoding.ASCII.GetString(write_buffer));
// close_pipe();
}
private void Async_Read_Completed(IAsyncResult result)
{
clientStream.EndRead(result);
Server_Message = ASCIIEncoding.ASCII.GetString(read_buffer);
this.Server_Message.Trim();
Console.WriteLine("Received from Server => " + Server_Message);
Debug.WriteLine("Received from Server => " + Server_Message);
if (clientStream.CanRead && clientStream.IsConnected)
{
Read_from_Server_Async();
}
else { close_pipe(); }
}
public Boolean Is_connected_to_server() {
return clientStream.IsConnected;
}
public void close_pipe()
{
if (clientStream != null)
{
if (clientStream.IsConnected)
{
clientStream.Close();
clientStream.Dispose();
Debug.WriteLine(" Pipe Closed");
}
}
}
}
}
Server side Main method implementation
static void Main(string[] args)
{
Asynchronus_NamedPipe_Server Async_server = new Asynchronus_NamedPipe_Server("mypipe7055");
while (true)
{
do
{
Async_server.Write_to_Client_Async("yeye");
Console.WriteLine("escape key");
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
}
}
Server Side Class -----
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Pipes;
using System.IO;
using System.ComponentModel;
using System.Diagnostics;
namespace Application_Pipe
{
public class Asynchronus_NamedPipe_Server
{
public readonly string pipe_address;
private System.IO.Pipes.NamedPipeServerStream namedPipeServerStream;
private string Server_Message;
public delegate void ASYNC_pipe_status_callback(string message);
private byte[] read_buffer = new byte[1024];
private byte[] write_buffer = new byte[1024];
public Asynchronus_NamedPipe_Server(string pipe_address)
{
try
{
this.pipe_address = pipe_address;
namedPipeServerStream = new NamedPipeServerStream(this.pipe_address,
PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous); //new NamedPipeServerStream(pipe_address);
Console.WriteLine("Connecting to Client...");
namedPipeServerStream.WaitForConnection();
Console.WriteLine("Connected to Client");
Read_from_Client_Async();
}
catch (Exception oEX) { Console.WriteLine(oEX.Message); }
}
public void Write_to_Client_Async(string message)
{
if (namedPipeServerStream != null)
{
if (namedPipeServerStream.CanWrite && namedPipeServerStream.IsConnected)
{
namedPipeServerStream.WaitForPipeDrain();
ASCIIEncoding.ASCII.GetBytes(message).CopyTo(write_buffer,0);
namedPipeServerStream.BeginWrite(write_buffer, 0, write_buffer.Length, new AsyncCallback(Async_Write_Completed), 2);
}
else { close_pipe(); }
}
}
public void Read_from_Client_Async()
{
if (namedPipeServerStream != null)
{
if (namedPipeServerStream.CanRead && namedPipeServerStream.IsConnected)
{
namedPipeServerStream.BeginRead(read_buffer, 0, read_buffer.Length, new AsyncCallback(Async_Read_Completed), 1);
} else { close_pipe(); }
}
}
private void Async_Read_Completed(IAsyncResult result)
{
namedPipeServerStream.EndRead(result);
this.Server_Message = ASCIIEncoding.ASCII.GetString(read_buffer);
this.Server_Message.Trim();
Debug.WriteLine("Received from Client => " + this.Server_Message+" <=REnd");
Read_from_Client_Async();
}
private void Async_Write_Completed(IAsyncResult result)
{
namedPipeServerStream.EndWrite(result);
Debug.WriteLine("Written To Client => " + ASCIIEncoding.ASCII.GetString(write_buffer));
}
public Boolean Is_connected_to_server()
{
return this.namedPipeServerStream.IsConnected;
}
public void close_pipe()
{
if(namedPipeServerStream.IsConnected){
namedPipeServerStream.Disconnect();
}
namedPipeServerStream.Close();
namedPipeServerStream.Dispose();
Debug.WriteLine(" Pipe Closed");
}
} //------class End
}

Related

C# Sending value from WebSocket Server Thread to Main()

I am trying to write a program to control home automation devices. This involves a WebSocket server that runs infinitely in a background thread listening for clients. The client sends JSON packets that contain settings. When the server gets a JSON packet, I want it to read and change any settings as needed in the Main()
I have a working WebSocket server and I have tried to use the PropertyChangedEvent but it never seems to see the handler. I suspect this occurs because they exist in different threads.
I have attached my code below as well as the example I have been working off of. There is a chance I am way off the mark here but this is the best I could find with the reading I have been doing.
Any help would be appreciated!
This is the Main():
using System;
using System.Threading;
using System.ComponentModel;
namespace HomeAutomation
{
class Controller
{
static void Main(string[] args)
{
bool passGo = false;
Thread SocketThread = new Thread(Socket.WebSocketServer);
SocketThread.IsBackground = true;
SocketThread.Start();
//This line lets the user know the Socket Thread is running in the background
Console.WriteLine("Socket Thread is running in the background: {0}", SocketThread.IsBackground);
do {
char input = Console.ReadKey().KeyChar;
if (input == 'x')
{
passGo = true;
}
} while (passGo == false);
Console.ReadLine();
/*
Settings s = new Settings();
s.PropertyChanged += new PropertyChangedEventHandler(S_PropertyChanged);
while (true)
{
string str = Console.ReadLine();
s.State = str;
}*/
}
public static void S_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Settings RecSettings = (Settings)sender;
Console.WriteLine("The {0} has changed to {1}", e.PropertyName, RecSettings.State);
}
}
public class Settings : INotifyPropertyChanged
//The Class Object 'Settings' is used to recieve the variable(s) from the client software
{
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
string state = string.Empty;
public string State
{
get { return state; }
set
{
state = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("State"));
Console.WriteLine("Event has been called");
}
}
}
}
}
This is my webSocket:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using Newtonsoft.Json;
namespace HomeAutomation
{
class Socket
{
public static void WebSocketServer()
{
//Declaring variables used in the program
IPAddress ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
TcpListener server = new TcpListener(ipAddress, 8080);
try
{
//Starts the server
server.Start();
Console.WriteLine("Starting Server...");
}
catch (Exception ex)
{
//If the server cannot start the error will be caught and printed to console
Console.WriteLine(ex.ToString());
Console.ReadLine();
}
while (true)
{
TcpClient client = server.AcceptTcpClient();
MakeNewConnection(client);
}
}
public static void MakeNewConnection(TcpClient client)
{
var thread = new Thread(NewClient);
thread.Start(client);
}
public static void NewClient(object data)
{
var client = (TcpClient)data;
Settings RecSettings = new Settings();
//Lets you know the address of the connected client
string address = client.Client.AddressFamily.ToString();
Console.WriteLine("{0} has connected!", address);
//creates a network stream for information to flow through
NetworkStream stream = client.GetStream();
byte[] receivedBuffer = new byte[100];
stream.Read(receivedBuffer, 0, receivedBuffer.Length);
StringBuilder msg = new StringBuilder();
foreach (byte b in receivedBuffer)
{
if (b.Equals(00))
{
break;
}
else
{
msg.Append(Convert.ToChar(b).ToString());
}
}
Console.WriteLine("Client Says: {0}", msg.ToString());
RecSettings = JsonConvert.DeserializeObject<Settings>(msg.ToString());
Console.WriteLine(RecSettings.State.ToString());
RecSettings.State = "Off";
int byteCount = Encoding.ASCII.GetByteCount("Thank you");
byte[] sendData = new byte[byteCount];
sendData = Encoding.ASCII.GetBytes("Thank you");
stream.Write(sendData, 0, sendData.Length);
}
}
}
This is the event handler example I am using:
using System;
using System.ComponentModel;
namespace HomeAutomation
{
class Program
{
static void Main(string[] args)
{
TestClass sample = new TestClass();
sample.PropertyChanged += new PropertyChangedEventHandler(sample_PropertyChanged);
while (true)
{
string str = Console.ReadLine();
int val;
if (int.TryParse(str, out val))
sample.TestValue = val;
}
}
static void sample_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
TestClass sample = (TestClass)sender;
/*
* Use expression behind if you have more the one property instead sample.TestValue
* typeof(TestClass).GetProperty(e.PropertyName).GetValue(sample, null)*/
Console.WriteLine("Value of property {0} was changed! New value is {1}", e.PropertyName, sample.TestValue);
}
}
public class TestClass : INotifyPropertyChanged
{
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
int testValue = 0;
public int TestValue
{
get { return testValue; }
set
{
testValue = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("TestValue"));
}
}
}
}
You may want to wrap the contents of your WebSocket response in code that invokes it in the Dispatcher thread.
System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
{
... response handler code
}

Bug in TCP/IP application

I wrote a client-server app, this is a console chat application for many clients. When only one client is connected, the application works well, but when two or more clients are connected I have a bug, after sending one message to the second client, he lost connection to the server and only first client can send a message to the server...
I used Task for asynchronous operations like listening port and sending messages. When one client sends a message to the server, it adds it to the list messages and resends to all clients to refresh all windows.
Server application:
using System;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Server
{
class Program
{
private static List<Client> clients = new List<Client>();
private static TcpListener listener = null;
private static StreamReader reader = null;
private static StreamWriter writer = null;
private static List<Task> clientTasks = new List<Task>();
private static List<string> messages = new List<string>();
public static void Main()
{
Console.Title = "Server";
try
{
listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 8080);
listener.Start();
Console.WriteLine("Server started...");
var connectTask = Task.Run(() => ConnectClients());
//var listenTask = Task.Run(() => ListenClients());
Task.WaitAll(connectTask);
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
if (listener != null)
{
listener.Stop();
}
}
}
private static void ConnectClients()
{
Console.WriteLine("Waiting for incoming client connections...");
while (true)
{
if (listener.Pending()) //if someone want to connect
{
clients.Add(new Client(listener.AcceptTcpClient(), "Client: " + (clients.Count + 1)));
Console.WriteLine(clients[clients.Count - 1].clientName + " connected to server.");
var newClientTask = Task.Run(() => HandleClient(clients[clients.Count - 1]));
clientTasks.Add(newClientTask); //start new task for new client
}
}
}
private static void HandleClient(Client TCPClient)
{
Console.WriteLine("Starting handle client");
string s = string.Empty;
writer = new StreamWriter(TCPClient.client.GetStream());
reader = new StreamReader(TCPClient.client.GetStream());
try
{
while (!(s = reader.ReadLine()).Equals("Exit") || (s == null))
{
if(!TCPClient.client.Connected)
{
Console.WriteLine("Client disconnected.");
clients.Remove(TCPClient);
}
Console.WriteLine("From client: " + TCPClient.clientName + " -> " + s);
messages.Add(TCPClient.clientName + ": " + s); //save new message
//Console.WriteLine(s);
foreach (Client c in clients) //refresh all connected clients
{
c.writer.WriteLine("%C"); //clear client
foreach (string msg in messages)
{
c.writer.WriteLine(msg);
c.writer.Flush();
}
}
}
//CloseServer();
}
catch (Exception e) { Console.WriteLine(e); }
Console.WriteLine("ending handle client");
}
private static void CloseServer()
{
reader.Close();
writer.Close();
clients.ForEach(tcpClient => tcpClient.client.Close());
}
}
}
Client information class:
using System.Net.Sockets;
using System.IO;
namespace Server
{
class Client
{
public TcpClient client;
public StreamWriter writer;
public string clientName;
public Client(TcpClient client, string clientName)
{
this.client = client;
writer = new StreamWriter(client.GetStream());
this.clientName = clientName;
}
}
}
Client application:
using System.Net.Sockets;
using System.Net;
using System.IO;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Client
{
class Program
{
private static TcpClient client = new TcpClient();
private static StreamReader reader;
private static StreamWriter writer;
private static bool refresh;
private static List<string> messages = new List<string>();
public static void Main()
{
Console.Title = "Client";
ConnectLoop();
//Task.WaitAll(sendTask, recieveTask); //wait for end of all tasks
}
private static void ConnectLoop()
{
bool refreshTask = false;
Task sendTask = null, recieveTask = null, updateConvTask = null;
while (true)
{
if(!client.Connected) //try to connect
{
refreshTask = true;
if(sendTask != null || recieveTask != null || updateConvTask != null)
{
sendTask.Dispose();
recieveTask.Dispose();
updateConvTask.Dispose();
sendTask = recieveTask = updateConvTask = null;
}
Console.WriteLine("Connecting to server...");
try
{
client.Connect(IPAddress.Parse("127.0.0.1"), 8080);
}
catch (SocketException) { }
Thread.Sleep(10);
}
else if(refreshTask) // \/ CONNECTED \/
{
Console.WriteLine("Connected.");
reader = new StreamReader(client.GetStream());
writer = new StreamWriter(client.GetStream());
sendTask = Task.Run(() => SendMessage()); //task for sending messages
recieveTask = Task.Run(() => RecieveMessage()); //task for recieving messages
updateConvTask = Task.Run(() => UpdateConversation()); //task for update console window
refreshTask = false;
}
}
}
private static void SendMessage()
{
string msgToSend = string.Empty;
do
{
Console.WriteLine("Enter a message to send to the server");
msgToSend = Console.ReadLine();
writer.WriteLine(msgToSend);
writer.Flush();
} while (!msgToSend.Equals("Exit"));
EndConnection();
}
private static void RecieveMessage()
{
try
{
while (client.Connected)
{
//Console.Clear();
string msg = reader.ReadLine();
if(msg != string.Empty)
{
if (msg == "%C") //special message from server, clear messages if recieve it
{
messages.Clear();
}
else
{
messages.Add(msg);
refresh = true; //refresh console window
}
}
//Console.Clear();
//Console.WriteLine(msgFromServer);
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private static void UpdateConversation()
{
//string conversationTmp = string.Empty;
try
{
while (true)
{
if (refresh) //only if refresh
{
refresh = false;
Console.Clear();
messages.ForEach(msg => Console.WriteLine(msg)); //write all messages
Console.WriteLine();
}
}
}
catch (Exception) { }
}
private static void EndConnection()
{
reader.Close();
writer.Close();
client.Close();
}
}
}
I know that my bug will be something stupid. I'm new to TCP/IP applications, could you give me links to some tutorials that use it and Tasks?
Thanks for any help.

WindowsService donĀ“t execute while

I'm doing a small windows service, it reads from a web service and stores the data in a local database, however, it does not finish executing the while (while it's a service), when I'm debugging it in vs 15 it works perfectly , Follow the code below.
PS: The code I used to debug I comment it before it starts, it arrives to enter the while, but only the first line and does not check the rest.
Program.cs
using System.ServiceProcess;
namespace rdi_server.service
{
static class Program
{
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
}
}
Service1.CS
using System;
using System.Configuration;
using System.ServiceProcess;
using System.Threading;
namespace rdi_server.service
{
public partial class Service1 : ServiceBase
{
private Thread _thread;
private Updater _updater = new Updater();
private readonly int Interval = Convert.ToInt32(ConfigurationManager.AppSettings["timer"]);
private readonly string Connection = ConfigurationManager.AppSettings["connection"];
private readonly Connector _usuarioConnector;
private readonly Connector _bandaConnector;
private readonly Connector _generoConnector;
private readonly Connector _musicaConnector;
public Service1()
{
_usuarioConnector = new Connector("UsuarioBase");
_bandaConnector = new Connector("BandaBase");
_generoConnector = new Connector("GeneroBase");
_musicaConnector = new Connector("MusicaBase");
InitializeComponent();
}
protected override void OnStart(string[] args)
{
StartDebug();
}
public void StartDebug()
{
_thread = new Thread(OnTime);
_thread.Name = "My Worker Thread";
_thread.Start();
}
protected override void OnStop()
{
}
protected void OnTime()
{
while (true)
{
EventLog.WriteEntry("Dentro do WHILE foi executado!");
_updater.Do(Connection, _usuarioConnector, _generoConnector, _bandaConnector, _musicaConnector);
EventLog.WriteEntry("Fim do while");
Thread.Sleep(Interval);
}
}
}
}
Updater.CS
using rdi_musica.core;
using System.Collections.Generic;
using System.Data.SqlClient;
namespace rdi_server.service
{
class Updater
{
public void Do(string Connection,
Connector usuario,
Connector genero,
Connector banda,
Connector musica)
{
var usuarios = Loader.LoadUsuarios(usuario);
var generos = Loader.LoadGeneros(genero);
var bandas = Loader.LoadBandas(banda);
var musicas = Loader.LoadMusicas(musica);
using (var connection = new SqlConnection(Connection))
{
connection.Open();
foreach (var _usuario in usuarios)
{
DomainDAO.InsertUsuario(connection, _usuario);
}
foreach (var _genero in generos)
{
DomainDAO.InsertGenero(connection, _genero);
}
foreach (var _banda in bandas)
{
DomainDAO.InsertBanda(connection, _banda);
}
foreach (var _musica in musicas)
{
DomainDAO.InsertMusica(connection, _musica);
}
}
}
}
}
What's probably happening is you have an unhandled exception happening somewhere, which is breaking out of your while loop.
You can use the windows event log in combination with try-catch to log your errors, without breaking your infinite loop:
protected void OnTime()
{
while (true)
{
try
{
EventLog.WriteEntry("Dentro do WHILE foi executado!");
_updater.Do(Connection, _usuarioConnector, _generoConnector, _bandaConnector, _musicaConnector);
EventLog.WriteEntry("Fim do while");
}
catch (Exception ex)
{
this.EventLog.WriteEntry("ERROR: " + ex.GetType().ToString() + " : " + ex.Message + " : " + ex.StackTrace, EventLogEntryType.Error);
}
Thread.Sleep(Interval);
}
}

HTTPS call via HttpClient Getting 404 - NOT FOUND

I've been going crazy over this particular problem. What I am trying to do is make an HTTPS Call to the server after a user clicks the sign up button. The server must add the new user to the database and send me back a user key. I've tested the httpClient class with a local LAMP server without HTTPS. Works fine. When I try to connect to the productions server with SSL I GET A 404 - NOT FOUND. I have double checked that the URL, CONTENT and Authorization is formatted well. As a matter of facted I codded it in a console application and it connects to the production server every time. It just does not work with the windows phone emulator or my windows phone. Been monitoring everything with fiddler. I've also used the WebClient class to no avail. PLEASE HELP!
Code below!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JailBird_ProtoType.Models
{
// CLASS USED TO FORMAT OBJECT TO JSON STRING
public class TestUser
{
public string Name { set; get; }
public string Email { get; set; }
public string Password { set; get; }
public List<string> Roles = new List<string>();
}
}
using Microsoft.Phone.Net.NetworkInformation;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace JailBird_ProtoType.Services
{
public class UploadJsonService
{
private BackgroundWorker bw = new BackgroundWorker();
public BackgroundWorker GetBackGroundWorker { get { return bw; } }
private HttpClient client = new HttpClient();
private HttpClient GetClient { get { return client; } }
private HttpResponseMessage response;
public HttpResponseMessage GetResponseMessage { get { return response; } }
// SET THE UPLOAD URL
private string uploadURL;
public string SetUploadURL { set { uploadURL = value; } }
// SET THE STRING DATA UPLOAD VALUE
private string jsonValue ="";
public string SetJsonValue { set { jsonValue = value; } }
private HttpContent httpContent;
public HttpContent GetHttpContent { get { return httpContent; } set { httpContent = value; } }
// SET THE METHOD TYPE UPLOAD VALUE
private string Method = "POST";
public string SetMethod { set { Method = value; } }
// CONSRUCTOR
public UploadJsonService()
{
SetUpClass();
}
public UploadJsonService(string url, string data)
{
SetUploadURL = url;
SetJsonValue = data;
SetUpClass();
}
public UploadJsonService(string url, string method, string data)
{
SetUploadURL = url;
SetJsonValue = data;
SetMethod = method;
SetUpClass();
}
private void SetUpClass()
{
bw.DoWork += new DoWorkEventHandler(DoWork);
httpContent = new StringContent(jsonValue);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
}
public void StartUpload()
{
try
{
bw.RunWorkerAsync(); // RUN BACKGROUND WORKER
}
catch (Exception) { }
}
public void CancelUpload()
{
// CANCEL ALL WORKER TASKS
try
{
client.Dispose();
httpContent = null;
bw.CancelAsync();
}
catch (Exception) { }
}
public void SetHeader(string header, string value)
{
client.DefaultRequestHeaders.Add(header, value);
}
private async void DoWork(object sender, DoWorkEventArgs e)
{
if (isConnectionReady())
{
try
{
if (Method.ToLower() == "post")
{
response = await client.PostAsync(new Uri(uploadURL, UriKind.Absolute), httpContent);
}
else if (Method.ToLower() == "push")
{
response = await client.PutAsync(new Uri(uploadURL, UriKind.Absolute), httpContent);
}
// DO SOMETHING WITH THE RESPONSE HERE
}
catch (Exception)
{
//UPDATE THE UI THREAD HERE
Deployment.Current.Dispatcher.BeginInvoke(new Action(() =>
{
MessageBox.Show("Upload did not complete successfully. Check your connection settings.", "Something Went Wrong", MessageBoxButton.OK);
}));
}
}
else
{
//UPDATE THE UI THREAD HERE
Deployment.Current.Dispatcher.BeginInvoke(new Action(() =>
{
MessageBox.Show("Check your phone's connection settings", "No Network Connection", MessageBoxButton.OK);
}));
}
}
// METHOD USED TO CHECK FOR NETWORK CONNECTION
private bool isConnectionReady()
{
bool internet = false;
//Check if network is available
if (DeviceNetworkInformation.IsNetworkAvailable)
{
internet = true;
}
return internet;
}
}
}
// THIS METHOD IS ACTIVATED IN THE SIGNUP BUTTON EVENT HANDLER
public void SendToServer()
{
// string user = JsonConvert.SerializeObject(App.ViewModel.Users[0]); // Get User Information
TestUser me = new TestUser() { Name="testName2", Password="password",Email="mail#mail.com"};
me.Roles.Add("User");
string meString = JsonConvert.SerializeObject(me);
if (App.Settings.Contains("FirstSignUp"))
{
service = new UploadJsonService(ConnectToServer.USER_UPLOAD_URL,"PUT",meString);
}
else
{
service = new UploadJsonService(ConnectToServer.USER_UPLOAD_URL,"POST",meString);
}
service.SetHeader("Authorization", "Basic " + ConnectToServer.Get64BitEncoding(ConnectToServer.SERVER_ADMIN));
service.GetBackGroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RunWorkerServiceCompleted);
service.StartUpload();
}
private void RunWorkerServiceCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// DO WORK AFTER THE BACKGROUND WORKER COMPLETES
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace JailBird_ProtoType.Services
{
// THIS CLASS HOLDS ALL SERVER INFORMATION
// FOR QUICK ACCESS AND CHANGE
public static class ConnectToServer
{
public static string SERVER_ADMIN = "admin:password";
// UPLOAD USER TO DB
public static string USER_UPLOAD_URL = "https://xx.xxx.xx.xxx:443/api/users";
public static string Get64BitEncoding(string key) {
byte[] convert = System.Text.Encoding.UTF8.GetBytes(key);
return System.Convert.ToBase64String(convert);
}
}
}
omitted real server address for security reasons.
Sorry my code is not structured Right. Been changing it around to get this to work.

Serial Communication gets back wrong answer when something is running in the background (like browsing the hard drive)

I have some big trouble with serial requests.
Description from what i want:
establish a serial connection, send serial requests to 6 temperature
sensors one by one (this is done every 0,5 second in a loop)
the question and answer-destination is stored in a List array
every request is started in a separate thread so the gui does not bug
while the programme waits for the sensor-hardware to answer
My problem:
The connection and the request is working fine, but if I am browsing data at the local hard drive the answer from the sensor-unit gets destroyed (negative algebraic sign or value from other sensor or simply wrong value).
How does this happen or how can I solve this?
Where I guess the problem might be:
In the private void ReceiveThread() of class SerialCommunication
Here is my code:
Class CommunicationArray:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hardwarecommunication
{
public class CommunicationArray
{
public string request { get; set; }
public object myObject { get; set; }
public string objectType { get; set; }
}
}
Class SerialCommunication
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.IO;
using System.IO.Ports;
using System.Windows.Forms;
namespace Hardwarecommunication
{
class SerialCommunication
{
Thread t2;
Thread t;
private SerialPort serialPort = new SerialPort("COM2", 115200, Parity.Even, 8, StopBits.One);
string serialAnswer = "";
private volatile bool _shouldStop;
private int counter;
List<CommunicationArray> ar = new List<CommunicationArray>();
object[] o = new object[3];
public void addListener(string request, object myObject, string objectType)
{
CommunicationArray sa = new CommunicationArray();
sa.request = request;
sa.myObject = myObject;
sa.objectType = objectType;
ar.Add(sa);
}
public void startListen()
{
t2 = new Thread(() => writeSerialPortThread());
t2.Start();
}
public void startSerialPort2()
{
try
{
serialPort.Open();
//MessageBox.Show("Connection opend!");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
public void stopSerialPort2()
{
try
{
if (serialPort.IsOpen == true)
// Connection closed
serialPort.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void writeSerialPortThread()
{
string request = "";
for (int i = 0; i < ar.Count(); i++)
{
request = ar[i].request;
//request = ((object[])ar[0])[0].ToString();
//if (!t.IsAlive)
//{
try
{
t = new Thread(ReceiveThread);
_shouldStop = false;
//MessageBox.Show("start thread");
t.Start();
serialPort.Write(request);
Thread.Sleep(50);
_shouldStop = true;
t.Join();
}
catch
{
}
Label tmpLabelObject = (Label)ar[i].myObject;
serialAnswer = serialAnswer.Replace("=", "");
if (tmpLabelObject.InvokeRequired)
{
MethodInvoker UpdateLabel = delegate
{
tmpLabelObject.Text = serialAnswer;
};
try
{
tmpLabelObject.Invoke(UpdateLabel);
}
catch
{
}
}
}
}
private void ReceiveThread()
{
//MessageBox.Show("in thread");
while (!_shouldStop)
{
serialAnswer = "";
try
{
//MessageBox.Show("in thread");
serialAnswer = serialPort.ReadTo("\r");
if (serialAnswer != "")
{
}
return;
}
catch (TimeoutException) { }
}
}
}
}
Class Form1 //to establish the connection and to start the Sensor request
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;
namespace Hardwarecommunication
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private SerialCommunication serialCommunication1 = new SerialCommunication();
private void Form1_Load(object sender, EventArgs e)
{
//start up serial connection
serialCommunication1.startSerialPort2();
}
private void buttonStart_Click(object sender, EventArgs e)
{
timerRecord.Enabled = true;
if (this.buttonStart.Text == "Start")
this.buttonStart.Text = "Stop";
else
this.buttonStart.Text = "Start";
}
private void timerRecord_Tick(object sender, EventArgs e)
{
if (this.buttonStart.Text == "Stop")
{
this.serialCommunication1.startListen();
}
}
private void buttonFillRequestArray_Click(object sender, EventArgs e)
{
this.serialCommunication1.addListener("$0BR00\r" + "\r", this.labelResult0, "label0"); //request to the hardware
this.serialCommunication1.addListener("$0BR01\r" + "\r", this.labelResult1, "label1");
this.serialCommunication1.addListener("$01R00\r" + "\r", this.labelResult2, "label2");
this.serialCommunication1.addListener("$01R01\r" + "\r", this.labelResult3, "label3");
this.serialCommunication1.addListener("$01R02\r" + "\r", this.labelResult4, "label4");
}
}
}
I woud be happy about any try to fix the problem.
I coud also upload the solution as .zip but you can't test it at all because you do not have the sensor hardware.
Note: serialPort.Write(string) is a non-blocking store into the output buffer.
That means the following won't guarantee you've even finished writing your request before you stop listening for a response:
serialPort.Write(request);
Thread.Sleep(50);
_shouldStop = true;
You could add:
while( serialPort.BytesToWrite > 0 ) Thread.Sleep(1); // force blocking
but it's ill advised.
One thing I'm wondering. There is only a single serial port here. Why do you want many different threads to work with it when you could manage the entire serial port interaction with a single thread? (Or at worse, 1 thread for input 1 thread for output)
To me it makes a lot more sense to store up requests into a queue of some kind and then peel them off one at a time for processing in a single thread. Responses could be similarly queued up or fired as events back to the caller.
EDIT: If you don't mind one read/write cycle at a time you could try:
string response;
lock(serialPort) {
// serialPort.DiscardInBuffer(); // only if garbage in buffer.
serialPort.Write(request);
response = serialPort.ReadTo("\r"); // this call will block till \r is read.
// be sure \r ends response (only 1)
}

Categories

Resources