valida tuvo traves thread subprocesos sirve que para operacion net form false cross control checkforillegalcrossthreadcalls calls acceso c# callback delegates event-handling autoresetevent

tuvo - thread invoke c#



C#Threading y eventos para el dispositivo pad pad (4)

Soy nuevo en C # y actualmente estoy trabajando en el código de back-end para admitir el PIN pad. Básicamente, mi código

OpenDevice() -> RequestPIN() -> key in PIN on PIN PAD -> GetResultPIN() -> ConsolePrintOutPIN() -> Print keyed PIN on the Console

No sé cómo escribir el hilo para esto, de modo que una vez que se pulsa la "tecla Enter" en el dispositivo después del PIN, el sistema se enrolla automáticamente para funcionar en GetResultPIN() . Entonces, con mi conocimiento básico, escribí los siguientes códigos usando Console.ReadLine() para separar cada procedimiento:

static void Main(string[] args) { // 1. Open PIN Pad device OpenDevice(); Console.ReadLine();// to hold up from the previous procedure, it is *not* for input data purpose // 2. Request PIN from PIN Pad device. // On the PIN Pad device, it reads: // "Key in the PIN: " RequestPIN(); Console.ReadLine();// to hold up from the previous procedure, it is *not* for input data purpose // 3. get PIN from the device GetResultPIN(); // 4. Print out on the Console ConsolePrintOutPIN(); Console.ReadLine();// to hold up from the previous procedure, it is *not* for input data purpose }

Pregunta: ¿Alguien puede darme alguna sugerencia sobre cómo usar threading / event / delegate que puede evitar el uso de Console.ReadLine() ?

Como se mencionó anteriormente, Console.ReadLine() se usa solo para detener el procedimiento (lo siento por mi ingenuidad de usarlo de esta manera ...) Una vez que uso Console.ReadLine() , entre RequestPIN() y GetResult() , el sistema al menos esperaría a que ingrese el PIN del PIN PAD (conectado a la computadora a través de USB, no desde el teclado), y luego presionaría cualquier tecla en el teclado para pasar Console.ReadLine() y GetResultPIN() podría obtener mi PIN desde PIN Pad ... todo el programa funciona ahora, no está listo para el cliente, porque está muy entrecortado, no fluye debido a Console.ReadLine() ... ...

Entonces, idealmente, todo el método fluiría en conjunto. Una vez que se abre el dispositivo, RequestPIN() debería aparecer en la pantalla de PIN Pad solicitando el número de PIN, alguien puede ingresar y presionar enter en PIN Pad y fluye naturalmente a GetResultPIN() y leer el resultado, y luego imprime el PIN en la consola ... `

o

si la persona no ingresa el PIN, el dispositivo esperaría 30 segundos y se GetResultPIN() directamente a GetResultPIN() e imprimirá "0000" en la consola.

He buscado pisando y delegado, pero no estoy seguro de cómo usarlos en esta situación ... ¡Gracias!

Referencia: RequestPin () y GetResultPIN se enumeran a continuación:

mIPAD.requestPIN(waitTime, pinMsg, minLen, maxLen, tone, option, ","); //This function wraps device command 0x04. //It directs the device to prompt the user to enter a PIN //by displaying one of five predetermined messages and playing // a specified sound. //The messages on the device’s screen look like the figures below. //The event associated with this function is //OnPINRequestCompleteEvent.

waitTime: tiempo que el dispositivo debe esperar para que el usuario comience a ingresar el PIN

pinMsg: Mensaje para mostrar como un mensaje de usuario, como "Ingresar PIN", "Reingresar PIN", "Verificar PIN", etc.

minLen y maxLen: longitud mínima y longitud máxima de PIN

tono: opción de tono de pitido

Opción: Verificar PIN, no verificar PIN, ISO0 FOrmat, formato ISO3

La salida sería: un entero, 0: éxito, no cero: error

public void GetResultPIN() { StringBuilder sb = new StringBuilder(); sb.Append(mIPAD.pin.KSN); // Key Serial Number: //a given number from the device, unique for each device sb.Append("," + mIPAD.pin.EPB); // EPB: encryption of PIN after Dubpt TripleDES, // essentially, EPB is PIN sb.Append("," + mIPAD.getStatusCode()); //status code: Zero is good/done // None-Zero is Error sb.Append("/r/n"); result = sb.ToString(); }

Básicamente, GetResultPIN () devuelve una cadena de código aleatorio, por ejemplo: 9A00030000047A2000AB,AD781711481B08A2,0 cuando el PIN es 9A00030000047A2000AB,AD781711481B08A2,0 . Si se omite la parte de entrada del pin, devolvería ,,0 .


Gracias por publicar ... La solución aún no es ideal ... También hice más pruebas con respecto a la función RequestPIN() . Tengo los siguientes cuatro escenarios:

  1. El usuario finaliza la waitTime PIN antes de que se waitTime el waitTime espera. onPINRequestComplete : OpStatus:0 KSN:9A00030000047A2000C8 EPB:39DED176D3EA40B9 ..............................
  2. El usuario no termina de waitTime el PIN cuando se está waitTime .
    onPINRequestComplete : OpStatus:2 KSN:00000000000000000000 EPB:0000000000000000 ..............................

  3. El usuario cancela la opción del teclado PIN al presionar la tecla "Cancelar X" en el teclado PIN.

    onPINRequestComplete : OpStatus:1 KSN:00000000000000000000 EPB:0000000000000000 ..............................

  4. El usuario no ingresa el PIN en absoluto durante waitTime, y luego waitTime se apaga.

    onPINRequestComplete : OpStatus:2 KSN:00000000000000000000 EPB:0000000000000000 .............................. Entonces, los escenarios 1 y 3 requerirían el hilo para despertar de inmediato, mientras que 2 y 4 requerirían que el hilo se despertara cuando el waiTime se apaga. Entonces, usar Thread.sleep(20*1000) dentro de GetResultPIN() funcionaría perfectamente para los escenarios 2 y 4. En cuanto a 1 y 3, el usuario tiene que esperar mucho tiempo ...

Por otro lado, encontré un código sobre el Event

Dentro de Car.cs :

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace WaitOnTasksToComplete { class Car { public event Action OnChange; private double speed; public double Speed { get { return speed; } set { speed = value; if (speed >= 60) { if (OnChange != null) { OnChange(); } } } } } }

Dentro de Program.cs :

using System; namespace WaitOnTasksToComplete { class Program { static void Main(string[] args) { Car c = new Car(); c.OnChange += C_OnChange; c.Speed = 5; c.Speed = 55; c.Speed = 65; c.Speed = 75; } private static void C_OnChange() { Console.WriteLine("Event fired: Car goes higher than 60 MPH."); } } }

Entonces, básicamente, una vez que la Car.speed del Car.speed salta por encima de 60, la alarma se mostraría. Estoy considerando tomar prestada la condición en mi situación: Inicializar OpStatus = -999 . Cuando OpStatus=0 or 1 , siga ejecutando GetResultPIN() y PrintMessagePIN() . Si OpStatus=2 or others , sigue esperando ...

Es solo mis pensamientos ... aún no tengo idea de cómo implementarlo ... Cualquier idea o sugerencia relacionada sería apreciada .....


Puedes reescribir tu API para:

  • hacer que GetResultPIN() devuelva un valor
  • use este valor como entrada para ConsolePrintOutPIN()

En GetResultPIN debes hacer una tarea para leer tu PIN y esperarlo.

Ver: https://msdn.microsoft.com/en-us/library/dd537610(v=vs.110).aspx

Puedes hacer algo como esto:

public string GetResultPIN() { StringBuilder sb = new StringBuilder(); sb.Append(mIPAD.pin.KSN); // Key Serial Number: //a given number from the device, unique for each device sb.Append("," + mIPAD.pin.EPB); // EPB: encryption of PIN after Dubpt TripleDES, // essentially, EPB is PIN sb.Append("," + mIPAD.getStatusCode()); //status code: Zero is good/done // None-Zero is Error sb.Append("/r/n"); Thread.Sleep(20*1000); // it is in milliseconds return sb.ToString(); }


Realmente es difícil saber si esto funcionará o no sin hardware para jugar ...

Esta es la forma en que lo visualicé trabajando:

static void Main() { OpenDevice(); RequestPIN(); if (GetResultPIN()) { // do something with the PIN: var pin = mIPAD.pin.EPB; // ... } else { Console.WriteLine("0000"); } } public static bool GetResultPIN() { TimeSpan timeout = TimeSpan.FromSeconds(30); System.Diagnostics.Stopwatch SW = new System.Diagnostics.Stopwatch(); SW.Start(); while (mIPAD.getStatusCode() != 0 && SW.Elapsed < timeout) { System.Threading.Thread.Sleep(50); // small call to prevent CPU usage ramping to 100% } return (mIPAD.getStatusCode() == 0); }


Ah, me di cuenta. Básicamente estoy usando subprocesos aquí. El flujo principal es OpenDevice()->RequestPIN()->Thread(()=>CheckOpStatus(getResultPIN)) -> Thread.Start() . Dentro del subproceso, se establece un ciclo para verificar cada medio segundo qué es OpStatus . Según mi publicación anterior, OpStatus es el parámetro de salida de PIN Pad, zero- success; non-zero: failure zero- success; non-zero: failure . Dicho esto, el ciclo continuará hasta que bool condition_WithinWaitTime o bool condition_NoKeyEvent rompa. Después de romper, invoque el getResultPIN y así sucesivamente ....

Aquí está mi código fuente, ya que la entrada PIN es una de mis funciones, el resto tiene un comportamiento muy similar en términos de programación (solicitud-> operación manual-> retroalimentación), así que también incluí una variable de delegado para representar todas las funciones (tarjeta deslizar, PIN, firma bla bla).

static void Main(string[] args) { OpenDevice(); EventGetPIN(); } static void EventGetPIN() { myDel getResult = new myDel(GetResultPIN); Thread thread1 = new Thread(() => CheckOpStatus(getResult)); myDel requestDel = new myDel(RequestPIN); requestDel(); thread1.Start(); } static void CheckOpStatus(Delegate getResult) { int count = 0; int checkingPeriod = 500; int totalWaitTime = waitTime * 1000 + offsetTime; string OpStatus; string ksnStart = mIPAD.getKSN(); string ksn = ksnStart; bool condition_WithinWaitTime = true; bool condition_NoKeyEvent = true; while (condition_WithinWaitTime & condition_NoKeyEvent) { count++; OpStatus = mIPAD.getStatusCode().ToString(); ksn = mIPAD.getKSN(); //Console.WriteLine(OpStatus); condition_WithinWaitTime = (count * checkingPeriod) < totalWaitTime; condition_NoKeyEvent = (ksn == ksnStart); Thread.Sleep(checkingPeriod); } getResult.DynamicInvoke(); }