【问题标题】:Can I filter message from a window in a different thread?我可以从不同线程的窗口中过滤消息吗?
【发布时间】:2012-04-06 10:16:12
【问题描述】:

我正在编写一个使用 TwainDotNet 进行扫描的应用程序。

一切正常,但扫描使用户界面无法使用。所以我决定在不同的线程中扫描,但我从来没有得到扫描成功的事件。所以我决定仔细研究一下实现:

public DataSourceManager(Identity applicationId, 
    IWindowsMessageHook messageHook)
{
    // Make a copy of the identity in case it gets modified
    ApplicationId = applicationId.Clone();

    ScanningComplete += delegate { };
    TransferImage += delegate { };

    _messageHook = messageHook;
    _messageHook.FilterMessageCallback = FilterMessage;
    IntPtr windowHandle = _messageHook.WindowHandle;

    _eventMessage.EventPtr =  
           Marshal.AllocHGlobal(Marshal.SizeOf(typeof(WindowsMessage)));

以及进行过滤的方法:

protected IntPtr FilterMessage(IntPtr hwnd, int msg, IntPtr wParam, 
    IntPtr lParam, ref bool handled)
{

通常此方法会过滤消息日志,但如果我在不同的线程中扫描,我不会收到任何消息。

我的代码的扫描部分是:

    var scanningThread = new Thread((ThreadStart) delegate
    {
        // Previously I got the main UI form here, but that didn't work either
        var form = new Form();
        var messageHook = new WinFormsWindowMessageHook(form.Handle);

        var scanner = new TwainEngine(messageHook);
        scanner.TransferImage += TransferImage;
        scanner.ScanningComplete += ScanningComplete;
        scanner.StartScanning(twainSettings);

    });
    scanningThread.Start();

我对 Win32 消息体系结构一无所知,因此任何有关我如何解决此问题或导致此问题的原因的意见都会有所帮助。

【问题讨论】:

  • 伙计,你走错路了。不要在不同的线程上制作表格。未显示的表格句柄毫无价值。您确定在等待扫描完成时没有阻止 GUI?
  • @Brannon:感谢您的回复。我确定我没有阻止任何东西。库自带的demo程序也有同样的问题。

标签: c# windows multithreading messages


【解决方案1】:

您的代码将无法正常工作,因为您在没有消息循环的线程上创建表单。如果这个库确实需要一个表单或消息循环并且它正在挂起 UI,那么除了它有设计问题之外,这可能是您可能想要考虑让第二个线程运行消息循环的非常罕见的场景之一。

要创建一个运行消息循环的线程,请使用Application.Run。您修改后的代码可能如下所示。

var scanningThread = new Thread((ThreadStart) delegate
{
    var form = new Form();
    form.Load += (sender, args) =>
    {
      var messageHook = new WinFormsWindowMessageHook(form.Handle);
      var scanner = new TwainEngine(messageHook);
      scanner.TransferImage += TransferImage;
      scanner.ScanningComplete += ScanningComplete;
      scanner.StartScanning(twainSettings);
    };   
    Application.Run(form);
});
scanningThread.Start();

我必须指出,拥有多个 UI 线程会导致一些奇怪的问题,因此通常不建议这样做。但是,就像我说的,您可能别无选择。此外,保持这两个 UI 线程上发生的所有活动完全分开。您不应尝试从该辅助 UI 线程访问在主 UI 线程上运行的 UI 控件。将会发生各种不可预测和惊人的问题。如果您需要强制在一个线程上执行某项操作,请使用 InvokeBeginInvoke 来编组委托的执行。

【讨论】:

  • 非常感谢您的回复。有时间我会试试的。
  • 非常感谢,我修改为隐藏表单,扫描完成后关闭。
猜你喜欢
  • 2017-09-03
  • 1970-01-01
  • 2012-02-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多