Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I create an event loop/message pipe in a console application?

I would like to create an console application which has some events registered. The problem is that those events are never fired. In this particular situation in a Windows Forms application I should invoke Application.Run(new Form()); after registering those events, but it is Console Application.

So I would like to create an event loop or message pipe if it is possible for that console application.

The application:

using Bonjour;
using System;
using System.Threading;

using Bonjour;
using System;
using System.Threading;

namespace ConsoleApplication4 {
    class Program {
        [STAThread]

        static void Main() {

            DNSSDService service = new DNSSDService();
            DNSSDEventManager eventManager = new DNSSDEventManager();
            eventManager.ServiceFound += new _IDNSSDEvents_ServiceFoundEventHandler(eventManager_ServiceFound);
            DNSSDService browse = service.Browse(0, 0, "_axis-video._tcp", null, eventManager);

            Console.ReadLine();
        }


        static void eventManager_ServiceFound(DNSSDService browser, DNSSDFlags flags, uint ifIndex, string serviceName, string regtype, string domain) {
            Console.WriteLine("browser: " + browser + "\nDNSSDFlags " + flags + "\nifIndex " + ifIndex + "\nserviceName: " + serviceName + "\nregtype: " + regtype + "\ndomain: " + domain);

            DNSSDEventManager eventManager1 = new DNSSDEventManager();
            eventManager1.ServiceResolved += new _IDNSSDEvents_ServiceResolvedEventHandler(eventManager_ServiceResolved);
            browser.Resolve(flags, ifIndex, serviceName, regtype, domain, eventManager1);
        }


        private static void eventManager_ServiceResolved(DNSSDService service, DNSSDFlags flags, uint ifIndex, string fullname, string hostname, ushort port, TXTRecord record) {
            Console.WriteLine("----------------------------------------");
            Console.WriteLine("FFFFFFFFFFFFFFFFFFFFFOUUUUUUUUUUUUUUUUND");
            Console.WriteLine("DNSSDService " + service + "\nDNSSDFlags " + flags + "\nifindex " + ifIndex + "\nfullname " + fullname + "hostname " + hostname + "\nport " + port + "\nrecord " + record);
            string s = record.ToString();
            Console.WriteLine("mac " + record.GetValueForKey("macaddress"));

            var str = System.Text.Encoding.Default.GetString(record.GetValueForKey("macaddress"));
            Console.WriteLine("mac " + str);
            Console.WriteLine("----------------------------------------");

            DNSSDEventManager eventManager = new DNSSDEventManager();
            eventManager.AddressFound += new _IDNSSDEvents_AddressFoundEventHandler(eventManager_AddressFound);
            DNSSDAddressFamily family = new DNSSDAddressFamily();
            service.GetAddrInfo(flags, ifIndex, family, hostname, eventManager);
        }


        private static void eventManager_AddressFound(DNSSDService service, DNSSDFlags flags, uint ifIndex, string hostname, DNSSDAddressFamily addressFamily, string address, uint ttl) {
            Console.WriteLine("----------------------------------------");
            Console.WriteLine(hostname);
            Console.WriteLine(address);
            Console.WriteLine("----------------------------------------");
        }
    }
}

enter code here

WPF Main0Window.xaml.cs

namespace HomeSecurity {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window {

        public MainWindow() {
            InitializeComponent();
        }


        private void Window_Loaded(object sender, RoutedEventArgs e) {
            createGUI();
        }


        private void createGUI() {
            Scanner.ScanService();

            //THIS CODE WON'T RUN BECAUSE   Scanner.ScanService(); have frozen it
            AddVideoStream("192.168.0.2");
            AddVideoStream("192.168.0.2");
            AddVideoStream("192.168.0.2");
        }


        //TEN
        private void AddVideoStream(String sourceIP) {
            int cols = 2;
            int formsHostWidth = (int)(VideoPanel.ActualWidth / cols) - 4;

            WindowsFormsHost formsHost = new WindowsFormsHost();
            VideoStream videoStream = new VideoStream(sourceIP);
            formsHost.Width = formsHostWidth;
            formsHost.Height = videoStream.GetPrefferedHeight(formsHostWidth);
            formsHost.Child = videoStream;
            Border lineBorder = new Border();
            lineBorder.BorderBrush = Brushes.Green;
            lineBorder.BorderThickness = new Thickness(2);
            lineBorder.Child = formsHost;
            VideoPanel.Children.Add(lineBorder);
        }
    }
}

And the class Scanner which has method ScanService:

using Bonjour;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HomeSecurity {
    class Scanner {
        [STAThread]
        public static void ScanService() {
            try {
                DNSSDService service = new DNSSDService();
                DNSSDEventManager eventManager = new DNSSDEventManager();
                eventManager.ServiceFound += new _IDNSSDEvents_ServiceFoundEventHandler(eventManager_ServiceFound);
                DNSSDService browse = service.Browse(0, 0, "_axis-video._tcp", null, eventManager);
                System.Windows.Threading.Dispatcher.Run(); // BLOCKS EVERYTHING
            } catch (Exception e) {

                Console.WriteLine("--------------------EXCEPTION-----------------");
                Console.WriteLine(e);
                Console.WriteLine("--------------------EXCEPTION-----------------");
            }
        }

        static void eventManager_ServiceFound(DNSSDService browser, DNSSDFlags flags, uint ifIndex, string serviceName, string regtype, string domain) {
            try {
                Console.WriteLine("---------------- eventManager_ServiceFound------------------------");
                Console.WriteLine("browser: " + browser + "\nDNSSDFlags " + flags + "\nifIndex " + ifIndex + "\nserviceName: " + serviceName + "\nregtype: " + regtype + "\ndomain: " + domain);
                Console.WriteLine("----------------------------------------");

                //   DNSSDService service2 = new DNSSDService();
                DNSSDEventManager eventManager1 = new DNSSDEventManager();
                eventManager1.ServiceResolved += new _IDNSSDEvents_ServiceResolvedEventHandler(eventManager_ServiceResolved);
                browser.Resolve(flags, ifIndex, serviceName, regtype, domain, eventManager1);
            }
            catch (Exception e) {

                Console.WriteLine("--------------------EXCEPTION--------eventManager_ServiceFound---------");
                Console.WriteLine(e);
                Console.WriteLine("--------------------EXCEPTION-----------------");
            }
         }

         private static void eventManager_ServiceResolved(DNSSDService service, DNSSDFlags flags, uint ifIndex, string fullname, string hostname, ushort port, TXTRecord record) {
             try {
                 Console.WriteLine("-------------------eventManager_ServiceResolved---------------------");
                 Console.WriteLine("DNSSDService " + service + "\nDNSSDFlags " + flags + "\nifindex " + ifIndex + "\nfullname " + fullname + "hostname " + hostname + "\nport " + port + "\nrecord " + record);
                 var str = System.Text.Encoding.Default.GetString(record.GetValueForKey("macaddress"));
                 Console.WriteLine("mac " + str);
                 Console.WriteLine("----------------------------------------");

                 //    DNSSDService service2 = new DNSSDService();
                 DNSSDEventManager eventManager = new DNSSDEventManager();
                 eventManager.AddressFound += new _IDNSSDEvents_AddressFoundEventHandler(eventManager_AddressFound);
                 DNSSDAddressFamily family = new DNSSDAddressFamily();
                 service.GetAddrInfo(flags, ifIndex, family, hostname, eventManager);
             }
             catch (Exception e) {

                 Console.WriteLine("--------------------EXCEPTION--------eventManager_ServiceResolved---------");
                 Console.WriteLine(e);
                 Console.WriteLine("--------------------EXCEPTION-----------------");
             }
         }

         private static void eventManager_AddressFound(DNSSDService service, DNSSDFlags flags, uint ifIndex, string hostname, DNSSDAddressFamily addressFamily, string address, uint ttl) {
             try {
                 Console.WriteLine("------------------eventManager_AddressFound----------------------");
                 Console.WriteLine("hosname " + hostname);
                 Console.WriteLine("address " + address);
                 Console.WriteLine("----------------------------------------");
             }
             catch (Exception e) {
                 Console.WriteLine("--------------------EXCEPTION-----eventManager_AddressFound------------");
                 Console.WriteLine(e);
                 Console.WriteLine("--------------------EXCEPTION-----------------");
             }
         }
    }
}
like image 304
Yoda Avatar asked Feb 14 '23 03:02

Yoda


1 Answers

I don't understand what your code sample has to do with events or Windows Forms. It looks like you're just using the ZeroConf .NET libraries, which doesn't appear to have anything to with Windows forms or event loops?

At any rate, if you want to create (and pump) a windows message loop on a background thread, you can do it using the WPF dispatcher class - call System.Windows.Threading.Dispatcher.Run() from a background thread.

If you don't want to use WPF, you can use Windows Forms - just call Application.Run(someForm);, but create someForm as a 0-width 0-height hidden window and set ShowInTaskBar = false on it, and that will create (and pump) a windows message loop too.


It looks like the ZeroConf libraries are COM objects, and the library is trying to post back to your main thread as it's using the STA (Single-Threaded-Apartment) threading model.

Here's a guess. If the COM objects are set up to use 'Both' as their threading model, then they'll pick STA, because you're creating the objects on your main thread, and by default the main thread of a .NET app is STAThread. Try deleting the [STAThread] attribute from your Main method, and putting an [MTAThread] attribute instead. If the ZeroConf COM objects are using 'Both' rather than STA as their threading model, then because you create them from an MTA thread, the events will be posted to arbitrary threadpool worker threads, instead of posted back to your main STA thread. If this is the case, this should solve it and you won't need to run a message loop at all. You'll have to write thread-safe code when processing your events though.

like image 86
Orion Edwards Avatar answered Apr 28 '23 06:04

Orion Edwards