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
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-----------------");
}
}
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With