Bonjour sdk для Windows работает только в потоке пользовательского интерфейса

Я разрабатываю программу, которая использует алгоритм Bonjour для поиска сервисов в сети. Я загрузил Bonjour SDK для Windows. На .Net было два примера приложений. Оба являются проектом Windows Forms. Образцы работают нормально, но когда я попытался реализовать образец консольного приложения, я получил AccessViolationException. Вот мой код:

class Program
{
    static void Main(string[] args)
    {
        DNSSDService service = new DNSSDService();
        DNSSDEventManager eventManager = new DNSSDEventManager();
        eventManager.ServiceFound += new _IDNSSDEvents_ServiceFoundEventHandler(eventManager_ServiceFound);
        //next line raises AccessViolationException
        DNSSDService browse = service.Browse(0, 0, "_psia._tcp", null, eventManager);

        Console.ReadKey();
    }

    static void eventManager_ServiceFound(DNSSDService browser, DNSSDFlags flags, uint ifIndex, string serviceName, string regtype, string domain)
    {
        //TODO: some logic
    }
}

Я нашел решение - все методы из библиотеки Bonjour должны вызываться из потока STA. Поэтому я добавил атрибут [STAThread] в метод Main. Теперь код выглядит так:

class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        DNSSDService service = new DNSSDService();
        DNSSDEventManager eventManager = new DNSSDEventManager();
        eventManager.ServiceFound += new _IDNSSDEvents_ServiceFoundEventHandler(eventManager_ServiceFound);
        DNSSDService browse = service.Browse(0, 0, "_psia._tcp", null, eventManager);

        Console.ReadKey();
    }

    static void eventManager_ServiceFound(DNSSDService browser, DNSSDFlags flags, uint ifIndex, string serviceName, string regtype, string domain)
    {
        //TODO: some logic
    }
}

Я решил проблему с AccessViolationException, но получил новое. После вызова метода Browse должно вызываться событие ServiceFound для каждой службы, определенной в сети. Но этого не произошло. После некоторого времени исследования я обнаружил, что мне нужно запустить насос сообщений, чтобы получать все эти события. Итак, окончательный код выглядит так:

 class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        DNSSDService service = new DNSSDService();
        DNSSDEventManager eventManager = new DNSSDEventManager();
        eventManager.ServiceFound += new _IDNSSDEvents_ServiceFoundEventHandler(eventManager_ServiceFound);
        DNSSDService browse = service.Browse(0, 0, "_psia._tcp", null, eventManager);

        Application.Run();
    }

    static void eventManager_ServiceFound(DNSSDService browser, DNSSDFlags flags, uint ifIndex, string serviceName, string regtype, string domain)
    {
        //TODO: some logic
    }
}

Чтобы остановить цикл сообщений, вызовите Application.Exit ().


person uzrgm    schedule 04.09.2012    source источник
comment
Вы мне очень помогли!!!! Вы знаете, как получить IP-адрес и порт в: eventManager_ServiceFound?   -  person Yoda    schedule 11.01.2014


Ответы (1)


Я попытался использовать ваш код, чтобы узнать IP-адрес ip-камеры, но я не знаю, что hostName я должен поставить, чтобы GetAddrInfo заработал.

using Bonjour;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApplication1 {
    static class Program {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [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);
            DNSSDService browse = service.Browse(0, 0, "_http._tcp", null, eventManager);


            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
        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 eventManager = new DNSSDEventManager();
            eventManager.AddressFound += new _IDNSSDEvents_AddressFoundEventHandler(eventManager_AddressFound);
            DNSSDAddressFamily family = new DNSSDAddressFamily();
            browser.GetAddrInfo(flags, ifIndex, family, "axis-00408cbeeae5", eventManager);

        }

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

        }



    }
}
person Yoda    schedule 11.01.2014