1

製造元から提供されたActiveXコントロールを使用してUSBカードリーダーを動作させるための小さなテストプログラムを作成しました。

別のスレッドを使用しない限り、フォームは正常に機能します。の新しいインスタンスを作成してイベントをReaderリッスンすると、すべてが正常に機能します。Readカードをスワイプすると、イベントが発生し、テキストボックスが更新されます。

private Reader _reader;

public Form1()
{
    InitializeComponent();
    CreateScanner();
}

public void CreateScanner()
{
    _reader = new Reader();
    _reader.Read += Read;
}

void Read(object sender, EventArgs e)
{
    CardData.Text = "Card Read";
}

役立つ場合のリーダークラス:

public class Reader
{
    private AxUSBHIDInsert _axUsbHid;
    public event EventHandler Read;

    public Reader()
    {
        _axUsbHid = new AxUSBHIDInsert();
        _axUsbHid.CreateControl();
        _axUsbHid.BeginInit();
        _axUsbHid.MSRReadDir = MSRReadDirection.ReadWithdrawal;
        _axUsbHid.EndInit();

        _axUsbHid.PortOpen = true;

        _axUsbHid.CardDataChanged += CardDataChanged;
    }

    void CardDataChanged(object sender, EventArgs e)
    {
        if (Read != null)
            Read(this, new EventArgs());
    }
}

ただし、これを別のスレッドで実行する必要があります。だから私はコンストラクターを次のように変更します

Thread thread = new Thread(CreateScanner);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();

STAスレッドである必要があります。そうでない場合、ActiveXコントロールはインスタンス化できないと文句を言います。ただし、これを行うと、イベントは発生しなくなります。私は糸脱毛がどのように機能するかについてあまりよく知らないので、理由はわかりません。

何か案は?コードは最終的には変更できないアプリケーションとともにデプロイされるクラスライブラリに存在するため、このように機能する必要があることに注意してください(別のスレッド、Readイベントに接続)。

4

1 に答える 1

2

COMオブジェクトは2番目のスレッドにメッセージを送信します。つまり、アプリケーションの実行中は常にメッセージが有効である必要があります。

このようにしてみてください:

public class Reader
{
  public Reader()
  {
    // leave empty
  }

  public Read() {
    _axUsbHid = new AxUSBHIDInsert();
    ...
  }
}

public Form1()
{
  InitializeComponent();
  _reader = new Reader();
  _reader.Read += Read;
  StartRead(_reader);
}

void StartRead(Reader reader) {
  Thread thread = new Thread(ReadRoutine);
  thread.SetApartmentState(ApartmentState.STA);
  thread.Start(reader);
}

void ReadRoutine(object param) {
  Reader reader = (Reader)param;
  reader.Read();
  while (AppIsAlive) { // add logic here
    // bad code, import GetMessage from user32.dll
    Application.DoEvents();
    Thread.Sleep(100);
  }
}

ただし、Readイベントは同期的に処理する必要があります。

void Read(object sender, EventArgs e)
{
  if (this.InvokeRequired)
    this.BeginInvoke(new EventHandler(Read), new object[2] { sender, e } );
  else {
    CardData.Text = "Card Read";
  }
}
于 2011-06-14T16:08:19.393 に答える