Waiting for HID Card Reader to be Connected - c#

I am writing an application that requires an HID card reader be connected to the system. Everything works properly when a card reader is already connected when the application is started, so I know I can find the device properly. (I am using the HID classes from PM> Install-Package hidlibrary.)
I want to add a feature where the program will display a prompt to connect a card reader if one is not found.
This is my first attempt:
public class App : Application
{
public static List<HidDevice> HidDeviceList;
// Block until device is plugged in
static ManualResetEvent m_WaitForPlugin = new ManualResetEvent(false);
// WMI Watcher for actual plug-in event
static ManagementEventWatcher watcher = new ManagementEventWatcher();
[STAThread()]
static void Main()
{
ShowSplashScreen();
FindCardReader();
CloseSplashScreen();
new App();
}
public App() : base()
{
StartupUri = new System.Uri("MainWindow.xaml", UriKind.Relative);
Run();
}
private static void FindCardReader()
{
ShowOnSplashScreen("Searching for card reader");
do
{
int VendorID = Convert.ToInt32(Settings.Default.ReaderVID, 16); // 0x0801
int ProductID = Convert.ToInt32(Settings.Default.ReaderPID, 16); // 0x0002
HidDeviceList = HidDevices.Enumerate(VendorID, ProductID).ToList();
if (HidDeviceList.Count > 0) {
break;
}
ShowOnSplashScreen("Please attach card reader...");
SetupWatcher();
m_WaitForPlugin.WaitOne();
} while (HidDeviceList.Count == 0);
}
private static void SetupWatcher()
{
WqlEventQuery query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2");
watcher.EventArrived += new EventArrivedEventHandler(delegate(Object sender, EventArrivedEventArgs e)
{
ShowOnSplashScreen("New device detected!");
m_WaitForPlugin.Set();
});
watcher.Query = query;
watcher.Start();
}
FindCardReader() in Main blocks as expected, but never appears to be signalled when a new device is plugged in. (I put a breakpoint in the delegate and it was never hit.)
I am not sure how to test the WMI watcher by itself (I tested the query in PowerShell and it appears to work). I also tried starting it in a new Thread, but the result was the same.

It turns out that there is a very clear deadlock in this code. I have re-architected the entire system to avoid the issue rather than add additional threads to handle the locking.

Related

C# TCP Server using infinite Loop unexpectedly closes

I am currently developing a C# TCP Server application for my game. The Server functions perfectly for a long period of time, closes however unexpectedly after about a day or 2 of running. I've furthermore printed the console output to a file, which I checked after the application closed, and there were no errors, or at least none were printed. The Code for the server is the following :
class Program
{
private static Thread consoleThread;
static void Main(string[] args)
{
//To get the output in a file
FileStream filestream = new FileStream("out.txt", FileMode.Create);
var streamwriter = new StreamWriter(filestream);
streamwriter.AutoFlush = true;
Console.SetOut(streamwriter);
Console.SetError(streamwriter);
InitializeConsoleThread();
ServerHandleData.InitializePacketListener();
ServerTCP.InitializeServer();
}
private static void InitializeConsoleThread()
{
consoleThread = new Thread(ConsoleLoop);
consoleThread.Name = "ConsoleThread";
consoleThread.Start();
}
private static void ConsoleLoop()
{
while (true)
{
}
}
}
The TCP Clients are handled with the following async methods :
private static void InitializeServerSocket()
{
ServerSocket = new TcpListener(IPAddress.Any, 8080);
ServerSocket.Start();
ServerSocket.BeginAcceptTcpClient(ClientConnectCallback, null); //Once we get a connection, ClientConnectCallback is called
}
private static void ClientConnectCallback(IAsyncResult result)
{
TcpClient tempClient = ServerSocket.EndAcceptTcpClient(result); //Accepts the connection and creates its corresponding TcpClient
ServerSocket.BeginAcceptTcpClient(ClientConnectCallback, null); //Open the connection again for other players
string[] IPs = tempClient.Client.RemoteEndPoint.ToString().Split(':');
if(IPDictionary.TryGetValue(IPs[0], out ClientObject C))
{
C.Socket = tempClient;
C.Socket.NoDelay = true;
C.Socket.ReceiveBufferSize = 4096;
C.Socket.SendBufferSize = 4096;
C.ReceiveBuffer = new byte[4096];
C.myStream = C.Socket.GetStream();
C.IP = tempClient.Client.RemoteEndPoint.ToString();
C.myStream.BeginRead(C.ReceiveBuffer, 0, C.Socket.ReceiveBufferSize, C.ReceiveCallback, null);
PACKET_SendMessage(C.ConnectionID, "CheckIP", 0, IPs[0]);
Console.WriteLine("Connection incoming from {0}", C.IP);
return;
}
Random ran = new Random();
int curID = ran.Next(); //random signed int
while (curID == 0 || ClientObjects.ContainsKey(curID)) { curID = ran.Next(); }
ClientObjects[curID] = new ClientObject(tempClient, curID);
TempPlayers[curID] = new TempPlayer();
}
which are called in the Program class with the initializeServer methods.
The Server functions well for a while and then suddenly closes, seemingly without any reason. The only cause I could find while searching on the internet is that the program eventually runs out of memory and just closes. Wouldn't however the garbage collector integrated in C# prevent such a thing ? Thank you all for your help in advance, I hope I made the question as direct and as clear as possible. Furthermore, if there are any other ways to improve these snippets of code, please do tell.

SqlDependency and Console app monitoring changes

I need your help. I'm trying to implement SqlDependency in a console app to constantly monitor a database table (ultimately a service broker queue). Here is my code and the problem is that after one execution application exits.
class Program
{
static void Main(string[] args)
{
var listener = new Listener();
listener.Listening();
Console.ReadKey();
}
}
public class Listener
{
const string notificationQuery = "SELECT [ID],[Name] FROM [dbo].[tblUsers]";
const string sampleConnectionString = #"Server = xxx; Database = yyy; Integrated Security = SSPI;";
public void Listening()
{
try
{
SqlClientPermission permission = new SqlClientPermission(PermissionState.Unrestricted);
permission.Demand();
}
catch (Exception ex)
{
}
using (var connection = new SqlConnection(sampleConnectionString))
{
connection.Open();
using (var command = new SqlCommand(notificationQuery, connection))
{
SqlDependency.Start(sampleConnectionString);
SqlDependency dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(OnDependencyChange);
var hasChanges = dependency.HasChanges;
command.ExecuteReader();
}
}
}
void OnDependencyChange(object sender, SqlNotificationEventArgs e)
{
Console.WriteLine(sender);
Listening();
}
What I found:
how to keep sql dependency doing the its purpose
but adding Listening(); to EventHandler doesn't help. When I'm debugging program and I add some value to the table event is triggered but this adds only one more execution of the Listening method while I want the app to keep working and monitoring the table all the time. Can someone help?

having problem making a multitask program to connect to an api

I have a list of stocks and I want to go through the list and get the price for every one of them and I want it, the program isn't cpu intensive so I need it to get all prices within one minute it also saves to a text file as it processes
the api I'm using will allow me to make 10k connections per min so DDos wont be a problem
The pc I will be running this program on has only one cpu so multithreading isn't an option I don't think
so far this is the code I've created
it works somewhat good on my multicore computer but still not fast enough but not well on single core computers
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Thread t = new Thread(Threads);
t.Start();
}
private object acctLock = new object();
static readonly object syncRoot = new object();
private void Threads()
{
string filePathAccounts = "";
if (radioButtonCarrierAccountsFile.Checked)
{
filePathAccounts = textBoxAccountsCarrier.Text;
}
List<string> stockList = File.ReadAllLines(filePathAccounts).ToList();
int accountPosition = 0;
int totalAccounts = stockList.Count;
Parallel.ForEach(stockList.AsParallel(), new ParallelOptions { MaxDegreeOfParallelism = Convert.ToInt32(textBoxThreads.Text) }, recipient =>
{
lock (acctLock)
{
string[] stockEntries = stockList[accountPosition].Split(',');
// This creates an array so we can add each line to its own variable
stock = stockList[Convert.ToInt32(0)];
++accountPosition;
}
// connecto to api and get info
string stockPrice = "Price received from api json";
lock (acctLock)
{
StreamWriter appendToFile = new StreamWriter("stockPrice.txt", true);
appendToFile.WriteLine($"{stock},{stockPrice}");
appendToFile.Dispose();
}
});
}

Troubles with Multithreads and Messaging Center in Xamarin.forms

I'm developing another sample where Messaging Center send status messages not coupled from device code to my view models.
At this point I used:
A alert message;
Label in my view;
A method by dependency injection from native code(interfaced and created before).
To notice the events before try in View models... etc
For it I used a static view instance in my share application constructor (App.xaml) where in view constructor I Subscript the status.
App (shared)
public partial class App : Application
{
public static ConnectViewModel CVM { get; set; }// Connection View Model
#region MasterDetailPage
public static MasterDetailPage MDP;
public static NavigationPage NAV = null;
public static MainView _mainpage;
#endregion
public App ()
{
InitializeComponent();
InitializeApplication();
NAV = new NavigationPage(new StarterView()) { BarBackgroundColor = Color.FromHex("701424"), BarTextColor = Color.White }; ;
MDP = new MasterDetailPage();
MDP.BackgroundColor = Xamarin.Forms.Color.FromHex("701424");
_mainpage = new MainView();
MDP.Master = _mainpage;
MDP.Detail = NAV;
MainPage = MDP;
MainPage.Title = "H2X";
}
private void InitializeApplication()
{
if (CVM == null)
{
CVM = new ConnectViewModel();
}
}
(View shared)
public MainView ()
{
InitializeComponent ();
string a="Test";
#region MessegeCenter
MessagingCenter.Subscribe<string,string>("APP", "Message_Received", async (sender,arg) =>
{
string b = a;
a = $"{arg}";
try
{
* await DisplayAlert(App.BM_Status, "Ok", "OK");*
}catch(Exception e)
{
string a = e.Message;
}
* generic_label_of_my_view = generic_label_of_my_view + "+";//It's not async one*
*string test = App.CVM.All_conn.Msg_Reciever();//Injection - It's not async one*
});
#endregion
}
Into the specific platform code (Device - UWP):
I create a timer that sends messages after some time instanced in mainpage constructor.
A HID device that notice me when some msg comes from USB.
The dispatcherTimer
void dispatcherTimer_Tick(object sender, object e)
{
DateTimeOffset time = DateTimeOffset.Now;
TimeSpan span = time - lastTime;
lastTime = time;
//Time since last tick should be very very close to Interval
TimerLog.Text += timesTicked + "\t time since last tick: " + span.ToString() + "\n";
timesTicked++;
if (timesTicked > timesToTick)
{
MessagingCenter.Send<string,string>("APP","Message_Received","MR");
}
}
The HIDInit and HID InputReport event
public async void HID_Init()
{
var selector = HidDevice.GetDeviceSelector(a_Id, b_Id, c_ID, d_ID);
var devices = await DeviceInformation.FindAllAsync(selector);
if (devices.Any())
{
// At this point the device is available to communicate with
// So we can send/receive HID reports from it generically
console_text = "HID devices found: " + devices.Count;
device = await HidDevice.FromIdAsync(devices.ElementAt(0).Id, FileAccessMode.ReadWrite);
if (device != null)
{
// At this point the device is available to communicate with
// create my input caller/event
device.InputReportReceived += inputReportReceived;//invoke caller
deviceWatcher = DeviceInformation.CreateWatcher(selector);
deviceWatcher.Removed += deviceRemovedEventHandler;//checa se nada foi removido
deviceWatcher.Start();
}
else
{
// There were no HID devices that met the selector criteria
throw new Exception("MUTT HID device not found");
}
}
else
{
// There were no HID devices that met the selector criteria
console_text = "HID device not found";
}
}
private void inputReportReceived(HidDevice sender, HidInputReportReceivedEventArgs args)
{
var bbytes = new byte[10];
wait_streaming = true;
DataReader dataReader = DataReader.FromBuffer(args.Report.Data);
dataReader.ReadBytes(bbytes);
console_text += System.Text.Encoding.ASCII.GetString(bbytes, 2, bbytes[1]);
is_read = false;
wait_streaming = false;
MessagingCenter.Send<string,string>("App","Message_Received","MR");
}
When I run any case with Dispatchertimer "works".
When I run by the Hidinputreport event with the alertmessage creates a system.exception in alertmessege line.
This is the "System.Exception"
if DEBUG && !DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
UnhandledException += (sender, e) =>
{
if (global::System.Diagnostics.Debugger.IsAttached) global::System.Diagnostics.Debugger.Break();
};
endif
When I run by the Hidinputreport event with the Label a marshalled interface crash with other thread in my call from messegingCenter in native code.
System.Exception: 'The application call a marshalled interface for another thread.
(Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))'
When I run the injection, works but I'm afraid that this Thread troubles make some semantical bug in my project cause I need to call INofifyPropertyChanged in shared code to print in my view the message but ...
Can I call it into the sender into Messeging Center Subscripte ?
How can I correct the other troubles with Threads ? Manual Reset Events ? EventWaitHandle ? (Inheritance:Object->MarshalByRefObject->WaitHandle->EventWaitHandle) ... so invasive way :/
I'm sorry if I ask some stupid question or show stupit code here ... but I don't know how to organize it WELL
Thank you in advance
Guilherme

Windows Service: The calling thread cannot access this object because a different thread owns it

Trying to convert XML files using XSL and printing the output. However, receiving the following message: The calling thread cannot access this object because a different thread owns it.
To set an interval for checking files, added a timer to the OnStart.
if (findPrinter() > 0)
{
System.Timers.Timer printNetterCheck = new System.Timers.Timer();
printNetterCheck.Elapsed += new ElapsedEventHandler(OnTimedEvent);
printNetterCheck.Interval = 30000;
printNetterCheck.Enabled = true;
}
The OnTimedEvent:
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
getFiles();
}
If any files available, call print:
foreach (string file in files)
{
try
{
StringWriter xslTransformResult = new StringWriter();
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(xslPath);
xslt.Transform(file, null, xslTransformResult);
if (print(xslTransformResult) == 1)
{
//do some things
The print function:
private int print(StringWriter transformedXML)
{
//assume OK
int rc = 1;
try
{
StringReader printNetterStreamReader = new StringReader(transformedXML.ToString());
PrintSystemJobInfo printNetterJob = printer.AddJob("PrintNetterPrint");
Stream printNetterStream = printNetterJob.JobStream;
Byte[] printNetterByteBuffer = UnicodeEncoding.Unicode.GetBytes(printNetterStreamReader.ReadToEnd());
printNetterStream.Write(printNetterByteBuffer, 0, printNetterByteBuffer.Length);
printNetterStream.Close();
}
catch (Exception e)
{
//return fail
rc = -1;
eventLog.WriteEntry("Error printing: " + e.Message, EventLogEntryType.Error);
}
return rc;
}
When calling print I receive the thread error. Found some stuff about Dispatchers etc.. but those are not available when using services.
Check PrintQueue.AddJob.
The method makes a COM call which requires the application be running in a single apartment (STA). The easiest way to fix that is to add STAThreadAttribute to Main which will force the application to run in a single thread. If you need multithreading in your application then you will need to implement the necessary plumbing to run the PrintQueue separately on an STA Thread.
// Create a factory to hold your printer configuration
// So that it can be retrieved on demand
// You might need to move the findPrinter() logic
public class PrintQueueFactory
{
private static PrintQueue _instance = new PrinterQueue(/* Details */);
public static PrintQueue PrintQueue { get { return _instance; } }
}
private int print(StringWriter transformedXML)
{
//assume OK
int rc = 1;
try
{
var printer = PrintQueueFactory.PrintQueue;
var staThread = new Thread(() => Print(printer, transformedXML.ToString()));
staThread.SetApartmentState(ApartmentState.STA);
staThread.Start();
staThread.Join();
}
catch (Exception e)
{
//return fail
rc = -1;
eventLog.WriteEntry("Error printing: " + e.Message, EventLogEntryType.Error);
}
return rc;
}
private static void Print(PrintQueue printer, string lines)
{
using(var printNetterJob = printer.AddJob("PrintNetterPrint"))
using(var printNetterStreamReader = new StringReader(lines))
using(var printNetterStream = printNetterJob.JobStream)
{
Byte[] printNetterByteBuffer = UnicodeEncoding.Unicode.GetBytes(printNetterStreamReader.ReadToEnd());
printNetterStream.Write(printNetterByteBuffer, 0, printNetterByteBuffer.Length);
}
}
maybe, as you are using a Timer control, it is related with multi-threading, maybe you should check if an Invoke is Required (InvokeRequired) in the Timer.Elapsed event handler.
If so, you should create a delegate to call this function, so it can be executed in the right thread.
Check this Invoke-Required question

Categories

Resources