Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在不同的线程上收听此事件?_C#_Multithreading_Sta - Fatal编程技术网

C# 如何在不同的线程上收听此事件?

C# 如何在不同的线程上收听此事件?,c#,multithreading,sta,C#,Multithreading,Sta,我制作了一个小测试程序,试图使用制造商提供的ActiveX控件让USB读卡器工作 只要不使用单独的线程,表单就可以正常工作。我创建了一个新的Reader实例,并收听Read事件,一切正常。我刷卡,事件触发,文本框得到更新 private Reader _reader; public Form1() { InitializeComponent(); CreateScanner(); } public void CreateScanner() { _reader = ne

我制作了一个小测试程序,试图使用制造商提供的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";
}
Reader类,以防有帮助:

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控件将抱怨无法实例化它。然而,这样做,事件不再触发。我不太熟悉线程是如何工作的,所以我不知道为什么


有什么想法吗?请注意,它必须以这种方式工作(独立线程,连接到读取事件),因为代码最终将驻留在一个类库中,该类库与我无法更改的应用程序一起部署。

您的COM对象将消息发送到第二个线程,这意味着它必须在应用程序运行的所有时间都处于活动状态

试着这样做:

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);
  }
}
但必须同步处理读取事件:

void Read(object sender, EventArgs e)
{
  if (this.InvokeRequired)
    this.BeginInvoke(new EventHandler(Read), new object[2] { sender, e } );
  else {
    CardData.Text = "Card Read";
  }
}

为什么需要在不同的线程上运行此程序?@Lasse,读卡器的代码只是实现了一个存在于更大应用程序中的现有接口。在新线程中创建类的代码位于其他库中。我不得不强迫它按原样工作。我试过你的代码,但仍然不起作用。我给了线程一个名称并检查了输出窗口,输出窗口显示线程仍在运行。不过,它并没有启动这项活动。我使用了您的确切代码(除了
Read
方法和
Read
eventhandler之间的命名冲突,所以我刚刚重命名了该方法。)正常情况下,这是有效的。不幸的是,我们不知道AxUSBHIDInsert(以及底层组件)是如何实现的。您可以尝试反之亦然:在主线程上读取USB卡,并在第二个线程上运行主窗口。