c # - Kan jeg filtrere besked fra et vindue i en anden tråd?

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg skriver en applikation, der bruger TwainDotNet til scanning.


Alt fungerer fint, men scanning gør brugergrænsefladen ubrugelig. Så jeg besluttede at scanne i en anden tråd, men jeg fik aldrig scanning succesfulde begivenhed. Så jeg besluttede at se nærmere på implementeringen:


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)));


Og den metode, der gør filtreringen:


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


Normalt filtrerer denne metode en log af meddelelser, men hvis jeg scanner i en anden tråd, modtager jeg ikke nogen.


Scanningsdelen af ​​min kode er:


    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();


Jeg ved intet om Win32-meddelelsesarkitekturen, så noget input på, hvordan jeg kunne løse dette problem, eller hvad der forårsager dette problem, ville være nyttigt.

Bedste reference


Koden du har virker ikke korrekt, fordi du opretter en formular på en tråd uden en meddelelsessløjfe. Hvis dette bibliotek virkelig kræver en formular eller et budskabsløkke, og det hænger op i brugergrænsefladen, så udover det at have designproblemer, kan dette være en af ​​de meget sjældne scenarier, hvor du måske vil overveje at have en anden tråd, der kører en meddelelsessløjfe.


For at oprette en tråd, der kører en meddelelsessløjfe, skal du bruge Application.Run. Din ændrede kode kan se sådan ud.


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();


Jeg må påpege at have mere end en brugergrænse kan medføre nogle mærkelige problemer, så det anbefales ikke generelt. Men som sagt har du måske ikke noget valg. Hold også al aktivitet på disse to UI-tråde helt adskilt. Du bør ikke forsøge at få adgang til UI-kontroller, der kører på din hovedbruger-tråd fra denne sekundære brugergrænseflade. Der er alle mulige uforudsigelige og spektakulære problemer, der vil opstå. Hvis du har brug for at tvinge en handling til at forekomme på en tråd, skal du bruge Invoke eller BeginInvoke til at marchere udførelsen af ​​en delegeret.