Obtaining Millisecond Resolution (cycle Time) in Windows Embedded Application - c#

I am making an Application in C# which reads CAN (Control Area Network) messages and sends them too. I need to do it in 10 milliseconds. The OS i am using is Windows Embedded 7 Pro.
public void ID0008Update10ms(DataTable supportPoints, int a)
{
System.TimeSpan timer10ms = System.TimeSpan.FromMilliseconds(10);
intialiseCAN();
while (a==1)
{
Stopwatch t = Stopwatch.StartNew();
sendCAN();
getCAN();
ID0006NavComStatus(supportPoints);
string state = Convert.ToString(gNavStatus);
while (t.Elapsed < timer10ms)
{ /*nothing*/}
}
}
The issue is the sendCAN() and reciveCAN() dynamically load the .dll file
public int sendCAN(ref can_msg msg, IntPtr pDll)
{
if (pDll == IntPtr.Zero)
{
MessageBox.Show("Loading Failed");
}
IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "CAN_Transmission");
CAN_Transmission sendCAN = (CAN_Transmission)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall, typeof(CAN_Transmission));
int result = sendCAN( ref msg);
return result;
}
This makes the cycle slow, I am not able to send the Message within 10ms. Can anyone propose a better way. Please remember. I use Windows Embedded.

You should move as much as possible outside the loop. If it doesn't absolutely have to be there, move it. Along the lines of....
private CAN_TransmissionMethod CAN_Transmission;
//Cache the delegate outside the loop.
private bool InitialiseCAN2(IntPtr pDll)
{
if (pDll == IntPtr.Zero)
{
Log("Loading Failed");
return false;
}
IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "CAN_Transmission");
CAN_Transmission = (CAN_TransmissionMethod)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall, typeof(CAN_Transmission));
return true;
}
public int sendCAN(ref can_msg msg)
{
if (CAN_Transmission == null)
return -1;//Can't send, no delegate, Log, Fail, Explode... make a cup of tea.
int result = CAN_Transmission( ref msg);
return result;
}
public void ID0008Update10ms(DataTable supportPoints, int a)
{
System.TimeSpan timer10ms = System.TimeSpan.FromMilliseconds(10);
intialiseCAN();
initialiseCAN2(pDll)
while (a==1)
{
Stopwatch t = Stopwatch.StartNew();
sendCAN(ref thereIsSupposedToBeAMessageHere);
getCAN(ref probablySupposedToBeSomethingHereToo);
ID0006NavComStatus(supportPoints);
string state = Convert.ToString(gNavStatus);
while (t.Elapsed < timer10ms)
{ /*nothing*/}
}
}

Related

How to get port a process is listening on in .net?

As several blogposts and Stackoverflow answers suggest, it is trivial to get this information via a combination of get-process and Get-NetTCPConnection commandlets. It is possible to execute these commands via .net code, parse the output and retrieve the information.
Is it not possible to get the port number a process is listening on in pure .net code using just the .net libraries? System.Diagnostics.Process.GetProcesByName returns a ton of information via the Process object, except for the port the process is listening on.
Any leads highly appreciated.
Unfortunately, IPGlobalProperties.GetIPGlobalProperties() does not return any information on which process is holding the socket, as it uses GetTcpTable not GetTcpTable2.
You would need to code it yourself. The below code works for TCP over IPv4. You would need similar code for UDP and IPv6.
[DllImport("Iphlpapi.dll", ExactSpelling = true)]
static extern int GetTcpTable2(
IntPtr TcpTable,
ref int SizePointer,
bool Order
);
[StructLayout(LayoutKind.Sequential)]
struct MIB_TCPTABLE
{
public int dwNumEntries;
}
[StructLayout(LayoutKind.Sequential)]
struct MIB_TCPROW2
{
public MIB_TCP_STATE dwState;
public int dwLocalAddr;
public byte localPort1;
public byte localPort2;
// Ports are only 16 bit values (in network WORD order, 3,4,1,2).
// There are reports where the high order bytes have garbage in them.
public byte ignoreLocalPort3;
public byte ignoreLocalPort4;
public int dwRemoteAddr;
public byte remotePort1;
public byte remotePort2;
// Ports are only 16 bit values (in network WORD order, 3,4,1,2).
// There are reports where the high order bytes have garbage in them.
public byte ignoreremotePort3;
public byte ignoreremotePort4;
public int dwOwningPid;
public TCP_CONNECTION_OFFLOAD_STATE dwOffloadState;
}
public enum MIB_TCP_STATE
{
Closed = 1,
Listen,
SynSent,
SynRcvd,
Established,
FinWait1,
FinWait2,
CloseWait,
Closing,
LastAck,
TimeWait,
DeleteTcb
}
enum TCP_CONNECTION_OFFLOAD_STATE
{
TcpConnectionOffloadStateInHost,
TcpConnectionOffloadStateOffloading,
TcpConnectionOffloadStateOffloaded,
TcpConnectionOffloadStateUploading,
TcpConnectionOffloadStateMax
}
static List<IPEndPoint> GetSocketsForProcess(int pid, MIB_TCP_STATE state = MIB_TCP_STATE.Established)
{
const int ERROR_INSUFFICIENT_BUFFER = 0x7A;
var size = 0;
var result = GetTcpTable2(IntPtr.Zero, ref size, false);
if (result != ERROR_INSUFFICIENT_BUFFER)
throw new Win32Exception(result);
var ptr = IntPtr.Zero;
try
{
ptr = Marshal.AllocHGlobal(size);
result = GetTcpTable2(ptr, ref size, false);
if (result != 0)
throw new Win32Exception(result);
var list = new List<IPEndPoint>();
var count = Marshal.ReadInt32(ptr);
var curPtr = ptr + Marshal.SizeOf<MIB_TCPTABLE>();
var length = Marshal.SizeOf<MIB_TCPROW2>();
for(var i = 0; i < count; i++)
{
var row = Marshal.PtrToStructure<MIB_TCPROW2>(curPtr);
if(row.dwOwningPid == pid && row.dwState == state)
list.Add(new IPEndPoint(row.dwLocalAddr, row.localPort1 << 8 | row.localPort2));
curPtr += length;
}
return list;
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
I had similar task not long ago. Here is complete .NET 6 code that you should be able to adopt for your particular needs:
public static int CheckConnection(string[] servers)
{
try
{
var srvs = servers.ToDictionary(k => k.Split("/", StringSplitOptions.RemoveEmptyEntries)[1], v => false);
IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] endPoints = ipProperties.GetActiveTcpListeners();
TcpConnectionInformation[] tcpConnections = ipProperties.GetActiveTcpConnections();
var count = 0;
foreach (var info in tcpConnections)
{
var ep = string.Format("{0}:{1}", info.RemoteEndPoint.Address, info.RemoteEndPoint.Port);
if (info.State.ToString().ToUpper() != "ESTABLISHED")
continue;
if (srvs.ContainsKey(ep))
{
count++;
srvs[ep] = true;
}
}
var sb = new StringBuilder();
foreach (var kvp in srvs)
{
sb.AppendFormat("{0,-21}: {1}", kvp.Key, kvp.Value ? "OK" : "FAIL");
sb.AppendLine();
}
Program.logger.Trace($"ZMQF. Connection check:\n{sb}");
return count;
}
catch (Exception ex)
{
Program.logger.Fatal(ex, $"ZMQF. CheckConnection exception. Servers: {(string.Join(",", servers))}");
return -1;
}
}

FatalExecutionEngineError when importing C++ dll

I have written an application which calls methods from a dll written in C++. It is a WinForms application, which has a WCF service self-hosted in it. One of the WCF methods is
called in 2-3 seconds periodically. The problem does not occur when only the WCF part is executed. The problem does no appear when only the SDK functions are called. However if
I start the WCF client which calls my method periodically, and the same time I execute some SDK functions, after 10 seconds a FatalExecutionEngineError (System.ExecutionEngineException).
exception is raised and the application crashes. I really don't know what could be the problem, or how to solve it. I suspect it is somehow related with the SDK, but I'm not sure, just a
feeling. Reading the related answers here in SO, maybe the method-imports are wrong? Here is what I got so far:
WCF class:
[ServiceContract]
public partial interface IWCFSample
{
[OperationContract]
string GetData(string param);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public partial class WCFSample : IWCFSample
{
#region Delegates
public delegate string OnGetDataDelegate(object sender, string getDataParam);
#endregion Delegates
#region Events
public event OnGetDataDelegate OnGetData;
#endregion Events
public string GetData(string serializedGetDataParam)
{
string res = string.Empty;
try
{
if (OnGetData != null)
{
res = OnGetData(this, (serializedGetDataParam));
}
}
catch
{
throw;
}
return res;
}
}
Initiated like this:
private ServiceHost _serviceHost;
private WCFSample _samplewcf;
private void Form1_Load(object sender, EventArgs e)
{
_samplewcf = new WCFSample();
_samplewcf.OnGetData += samplewcfOnGetData;
_serviceHost = new ServiceHost(_samplewcf);
_serviceHost.Open();
bw = new BackgroundWorker();
bw.WorkerSupportsCancellation = true;
bw.DoWork += (o, args) =>
{
WCFSampleClient client = new WCFSampleClient();
while (true)
{
if (bw.CancellationPending)
{
return;
}
client.GetData(DateTime.Now.ToString());
Thread.Sleep(200);
}
};
bw.RunWorkerAsync();
}
private string samplewcfOnGetData(object sender, string getDataParam)
{
richTextBox1.Text += "GetData Called - " + getDataParam + "\n";
richTextBox1.SelectionStart = richTextBox1.Text.Length;
richTextBox1.ScrollToCaret();
return getDataParam;
}
The C++ related parts are pretty long, but here are the imports I use.
int OpenDevice (char* strUSBName, int iPortNum )
Imported as:
[DllImport("TP9000.dll")]
public static extern int OpenDevice(string USBNam, int portnum);
int CheckFeeder (int* nCheck)
Imported as:
[DllImport("TP9000.dll")]
public static extern int CheckFeeder(ref int pStatus);
int DP_GetSensorStatus (BYTE *pRailStatus, BYTE *pFeedRollerStatus, BYTE *pTraySensorState)
Imported as:
[DllImport("TP9000.dll")]
public static extern int DP_GetSensorStatus(ref byte pRailStatus, ref byte pFeedRollerStatus, byte[] pTraySensorState);
int PathSenser(int *pStatus)
Imported as:
[DllImport("TP9000.dll")]
public static extern int PathSenser(ref int p1);
int CheckRibbonEx( int *nRibbon, int *nTagRibbon)
Imported as:
[DllImport("TP9000.dll")]
public static extern int CheckRibbonEx(ref int nRibbon, ref int nTagRibbon);
int N_EndOfPrint(int nPanel, int *pPanelCount, int *pJobNo)
Imported as:
[DllImport("TP9000.dll")]
public static extern int N_EndOfPrint(int p1, ref int p2, ref int p3);
int N_PrintJobStatus (int *pJobStatus )
Imported as:
[DllImport("TP9000.dll")]
public static extern int N_PrintJobStatus(int[] p1);
UPDATE:
It seems that the last import is wrong:
int N_PrintJobStatus (int *pJobStatus )
Imported as:
[DllImport("TP9000.dll")]
public static extern int N_PrintJobStatus(int[] p1);
If I don't call this function in my code, it does not hang. But how should I marshal it. The documentation says:
It checks the status of the printing.
int N_PrintJobStatus (int *pJobStatus )
Parameter pJobStatus[out]:
JobStatus[0] = Priter Status : idle(0x00), in printing(0x01), Error-Printing Stop(0xFF)
JobStatus[1] = No Standby Job (on Error, No pausing Job)
JobStatus[2] = the number of standby job (including the currently operating job)
JobStatus[3] = the number of copies of the currently operating job(total number of printing copies)
JobStatus[4] = the number of copies of the remaining jobs (Remaining Count)
JobStatus[5] = if the re-printig checking window displays or not. 1: AUTO Option display, 2:Manual option display, 0: No Checking Window
JobStatus[6] = it checks the error processing and status message level (1~4) then show 0t at retprinting checking window(Auto Option)
Open the printer and then check the ribbon.
Card is ejecting
Ribbon is being synchronized
If you want to re-print, please press “OK” button.( make “OK” button activated)
Return value 0: Success. -1: Failure. (Get_Status)
Okay, without the rest of the code it was impossible to solve this. The wrong code was the following:
int[] nJobSt = { 0, 0, 0, 0, 0, 0 }; //notice that the array length is 6
LastErrorCode = TP9000Dll.N_PrintJobStatus(nJobSt);
From the SDK documentation we should assume the function needs an array length of 7
So the correct code is:
int[] nJobSt = { 0, 0, 0, 0, 0, 0, 0 }; //notice that the array length is 7
LastErrorCode = TP9000Dll.N_PrintJobStatus(nJobSt);
The conclusion: Read every documentation 3 times, never trust the sample applications which are coming with the SDK.

Serial port: Polling vs Event-Driven approach

I am using Win32 API (Overlapped IO) for serial port communication. I have used PInvoke to call the Win32 API from my C# code.
In my previous implementation, the receiver thread reads data by using Polling mechanism (Infinite while loop reads RX buffer periodically). Now, I am trying to use Event-Driven approach to read the data (Using WaitCommEvent API Call). We expect the new implementation will reduce the CPU usage and Speed-Up the communication.
But, After changing to Event-Driven approach, the communication is actually slowed down, taking twice the time to read when compared to Polling mechanism.
Can anyone suggest which one of these is the best approach improve the communication speed and reduce the CPU usage?
Below is my code snippet:
private void ReadDataForWindows()
{
var data = new byte[255];
// Specify a set of events to be monitored for the port.
if (SetCommMask(this.Handle, EV_DEFAULT))
{
while (this.Handle != (IntPtr)INVALID_HANDLE_VALUE)
{
uint eventMask = 0;
// Wait for an event to occur for the port.
eventMask = this.WaitForEvent();
if (eventMask == EV_RXCHAR)
{
this.ReadFromRXBuffer(data);
}
else if (eventMask == EV_ERR)
{
uint errors;
ClearCommError(this.Handle, out errors, IntPtr.Zero);
}
// Re-specify the set of events to be monitored for the port.
if (!SetCommMask(this.Handle, EV_DEFAULT))
{
break;
}
}
}
}
private void ReadFromRXBuffer(byte[] data)
{
uint dwBytesTransferred;
// Loop for waiting for the data.
do
{
// Read the data from the serial port.
this.Read(data, 255, out dwBytesTransferred);
// Display the data read.
if (dwBytesTransferred > 0)
{
if (this.DataReceived != null)
{
var dataReceived = new byte[dwBytesTransferred];
for (var i = 0; i < dwBytesTransferred; i++)
{
dataReceived[i] = data[i];
}
this.DataReceived(this, new ByteDataReceivedEventArgs(dataReceived, Convert.ToInt32(dwBytesTransferred)));
}
}
} while (dwBytesTransferred > 0);
}
private uint WaitForEvent()
{
uint eventMask = 0;
IntPtr evPtr = Marshal.AllocHGlobal(Marshal.SizeOf(eventMask));
Marshal.WriteInt32(evPtr, 0);
if (WaitCommEvent(this.Handle, evPtr, this.RxOvr.MemPtr) == false)
{
int error = Marshal.GetLastWin32Error();
// Operation is executing in the background
if (error == ERROR_IO_PENDING)
{
this.ReceiveSignal.WaitOne();
}
else
{
this.Fault = "WaitCommEvent() Failed. System Returned Error Code: " +
error.ToString();
return 0;
}
}
eventMask = (uint)Marshal.ReadInt32(evPtr);
return eventMask;
}

EnumWindows doesn't work properly

I'm trying to take process names as a string from a listBox in a for loop and search for all windows of those applications. When I add items manually to the listBox, it works fine; but when I use an embedded text file to store and load process names to the listBox, it searches for all items but finds only the last one. For the other ones, Process.GetProcessesByName() throws an exception: Sequence contains no elements.
[DllImport("user32.dll")]
static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);
static IEnumerable<IntPtr> EnumerateProcessWindowHandles(int processId)
{
var handles = new List<IntPtr>();
foreach (ProcessThread thread in Process.GetProcessById(processId).Threads)
EnumThreadWindows(thread.Id, (hWnd, lParam) => { handles.Add(hWnd); return true; }, IntPtr.Zero);
return handles;
}
Searching algorithm:
public void searchForApplications()
{
for (int i = 0; i < listBox1.Items.Count; i++)
{
try
{
foreach (var handle in EnumerateProcessWindowHandles
(Process.GetProcessesByName(listBox1.Items[i].ToString()).First().Id))
{
StringBuilder message = new StringBuilder(1000);
SendMessage(handle, WM_GETTEXT, message.Capacity, message);
if (message.ToString().Length > 0)
{
addNewApplication(new Applications(message.ToString(), message.ToString(),
int.Parse(handle.ToString())));
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
Thank you.
If GetProcessesByName doesn't find any processes matching the name you passed in (check your list), then it will return an empty array and First() will throw an InvalidOperationException. You should probably use FirstOrDefault() and check for null before getting the Id:
// ...
var process = Process.GetProcessesByName(listBox1.Items[i].ToString()).FirstOrDefault();
if (process != null)
{
foreach (var handle in EnumerateProcessWindowHandles(process.Id))
{
// ...
}
}
// ...

Sockets in C++ and C# under Windows not working properly

I'm using UDP sockets to communicate a C++ application with a C# application.
In the C# -> C++ direction everything seems to be working fine, but the other way around is the one that's driving me nuts.
Communication does work, but messages are getting way late (like 2 secs delay) in the C# app, even though they're being sent every frame (it's a 3D app), and the receiving code is executing every 10 ms.
I need real time so this is a very painful problem. Do you think this might be related to packet losses? Then why don't they get lost in the other direction?
EDIT:
C# app code for syncing data:
public void RecibeDatos()
{
if (MessageReceived && U != null && S != null)
{
MessageReceived = false;
//Console.WriteLine("listening for messages");
U.BeginReceive(ReceiveCallback, S);
}
}
public void ReceiveCallback(IAsyncResult ar)
{
UdpClient u = ((UdpState)(ar.AsyncState)).U;
IPEndPoint e = ((UdpState)(ar.AsyncState)).E;
receivedBytes = u.EndReceive(ar, ref e);
//int currentProtocol = (int) numero;
//ResetSignal = reset > 0;
//Console.WriteLine("Received: " + currentProtocol);
MessageReceived = true;
}
C++ Code for sending data:
float indiceFloat[1];
indiceFloat[0] = indice_protocolo_actual;
sender->setBuffer((void *)indiceFloat, sizeof(indiceFloat));
sender->sync();
sync method on J_Enviar (sender) class:
void J_Enviar::sync( void )
{
if(!_initialized) init();
if( _buffer == 0L )
{
fprintf( stderr, "Broadcaster::sync() - No buffer\n" );
return;
}
#if defined (WIN32) && !defined(__CYGWIN__)
unsigned int size = sizeof( SOCKADDR_IN );
sendto( _so, (const char *)_buffer, _buffer_size, 0, (struct sockaddr *)&saddr, size );
int err = WSAGetLastError ();
if (err!=0)
fprintf( stderr, "Broadcaster::sync() - error %d\n",err );
#else
unsigned int size = sizeof( struct sockaddr_in );
sendto( _so, (const void *)_buffer, _buffer_size, 0, (struct sockaddr *)&saddr, size );
#endif
}
Providing full SocketManager code for Receiving C# end:
using System;
using System.Net;
using System.Net.Sockets;
namespace WpfApplication1
{
public class SocketManager
{
private static SocketManager _instance = null;
static readonly object Padlock = new object();
private IPEndPoint E;
private UdpClient U;
private UdpState S;
private byte[] receivedBytes;
public static bool MessageReceived = true;
private SocketManager()
{
}
public byte[] ReceivedBytes
{
get { return receivedBytes; }
}
public static SocketManager Instance
{
get
{
lock(Padlock)
{
return _instance ?? (_instance = new SocketManager());
}
}
}
public void CreateReceivingSocket(IPAddress a, int puerto)
{
if(E==null || (E.Address != a && E.Port != puerto))
{
E = new IPEndPoint(a, puerto);
U = new UdpClient(puerto);
S = new UdpState { E = E, U = U };
}
}
public void ReceiveCallback(IAsyncResult ar)
{
UdpClient u = ((UdpState)(ar.AsyncState)).U;
IPEndPoint e = ((UdpState)(ar.AsyncState)).E;
receivedBytes = u.EndReceive(ar, ref e);
//int currentProtocol = (int) numero;
//ResetSignal = reset > 0;
//Console.WriteLine("Received: " + currentProtocol);
MessageReceived = true;
}
public void RecibeDatos()
{
if (MessageReceived && U != null && S != null)
{
MessageReceived = false;
//Console.WriteLine("listening for messages");
U.BeginReceive(ReceiveCallback, S);
}
}
public void CloseConnection()
{
if (E != null)
{
E.Port = 5502;
E = null;
}
if (U != null)
U.Close();
}
}
public class UdpState
{
public IPEndPoint E;
public UdpClient U;
}
}
And this is my dispatchertimerclick which makes the program receive each 10 ms:
_dispatcherTimer.Tick += DispatcherTimerTick;
_dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 1);
_dispatcherTimer.Start();
private void DispatcherTimerTick(object sender, EventArgs e)
{
_exp1Class.sendData();
_sm.RecibeDatos();
byte[] recibidos = _sm.ReceivedBytes;
if (recibidos != null)
{
float numero = BitConverter.ToSingle(recibidos, 0);
_exp1Class.CurrentProtocol = (int) numero;
}
}
I don't see when you kick off your first BeginReceive. (Ah, it is done from your first timer tick I think?) It should be initaited as soon as you are ready to receive data. Secondly, your ReceiveCallback should take the received data and place it into a queue of some sort and immediately call BeginReceive again. Otherwise you are holding up thge arrival of the next data frame until the prior was consumed. Finally, watch for threading issues, as the Threading timer and the UDP callback each will run on seperate threads from your application main thread.
The only reason your code works at all is because you pre-initialized MessageReceived = true even before you receive any callbacks. When the first tick happens the call to RecibeDatos invokes BeginReceive because that bool was set to true.
Think of BeginReceive as saying "call me back when you have some data from the network". You don't need to poll the network using your timer. (You can choose to consume that data via your timer if your application requires that, but lets leave that aside for the moment).
Here are the rough steps:
First, upon start (or enable, run, etc) you should call BeginReceive. You will now receive a notification when data arrives.
Secondly, when the callback happens you complete that read of the data bytes using EndReceive. That data would typically be buffered or otherwise dispatched. You should then call BeginReceive again (within the callback) so that upon the next set of data being available you will again get notified. It becomes a kind of async loop.
The question is what to do with the data you are reading. You might consider placing the data into a queue, and then having your Timer pop these data frames off of the queue for processing. Be aware that the data can arrive multiple times between your Ticks.

Categories

Resources