0

我正在尝试使用 C# 将 IP 地址异步解析为主机名,然后将结果添加到 ListBox。异步操作工作正常,但我无法将解析的名称添加到列表框中,因为另一个线程拥有它。如何绕过此问题并将解析的名称添加到列表框中。

这是我到目前为止所做的

public static ManualResetEvent GetHostEntryFinished = new ManualResetEvent(false);            

            private void AsyncDNSResolver(string IPString)
        {
        GetHostEntryFinished.Reset();

        IPHostEntry host = new IPHostEntry();
        host.AddressList = new IPAddress[] { IPAddress.Parse(IPString) };
        Dns.BeginGetHostEntry(host.AddressList[0], new AsyncCallback(GetHostEntryCallback), host);

        GetHostEntryFinished.WaitOne();

    }

    public static void GetHostEntryCallback(IAsyncResult ar)
    {
        IPHostEntry host = (IPHostEntry)ar.AsyncState;
        while (!ar.IsCompleted) ;
        host = Dns.EndGetHostEntry(ar);
       lsvHosts.items.add(host.HostName);
     GetHostEntryFinished.Set();
    } 
4

2 回答 2

1

如果您想在单独的线程上执行昂贵的活动并在等待结果的同时继续工作,您可以使用此代码片段。

static void Main(string[] args)
{
    Console.WriteLine("About to call DNS");
    ResolveDnsAndPerformWorkWhileWaiting("74.125.237.112");
    Console.Read();
}

public static void ResolveDnsAndPerformWorkWhileWaiting(string ipaddress)
{
    var task = new Task<string>(() =>
        {
            var host = new IPHostEntry { AddressList = new[] { IPAddress.Parse(ipaddress) } };
            var result = Dns.GetHostEntry(host.AddressList[0]);
            return result.HostName;
        });

    // execute the work on another thread
    task.Start();

    // do other stuff

    // use the results (if the task has not finished the .Result property will hold until completed)
    var resolvedAddress = task.Result;
    Console.WriteLine("Resolved address:" + resolvedAddress);
}

如果您使用的是 Windows 窗体应用程序,那么最简单的方法是使用BackgroundWorker,这是一个代码示例

static void Main(string[] args)
{
    Console.WriteLine("About to call DNS");

    var worker = new BackgroundWorker();
    worker.DoWork += worker_DoWork;
    worker.RunWorkerCompleted += worker_RunWorkerCompleted;
    worker.RunWorkerAsync("74.125.237.112");


    Console.Read();
}

static void worker_DoWork(object sender, DoWorkEventArgs e)
{
    var host = new IPHostEntry { AddressList = new[] { IPAddress.Parse((string)e.Argument) } };
    var result = Dns.GetHostEntry(host.AddressList[0]);

    e.Result = result.HostName;
}

static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // You could set your UI control here like label1.text = (string)e.Result
    Console.WriteLine((string)e.Result);
}
于 2012-10-23T10:28:16.333 回答
1

目的是您将继续执行GetHostEntryCallback(在 内可能是匿名的AsyncDNSResolver)并引发另一个事件以将数据返回给调用者。这就是您可用的异步编程模型的本质(C# 5 之前的版本)。在这种情况下,AsyncDNSResolver无法返回string,因为它在退出时将不可用。

您的选择归结为:

  1. 通过引发事件(或调用另一个回调)来拥抱异步,而不是尝试从AsyncDNSResolver
  2. 停止使用异步方法并改用阻塞Dns.GetHostEntry
于 2012-10-23T10:18:32.777 回答