0

C#を使用してIPアドレスをホスト名に非同期的に解決し、その結果をリストボックスに追加しようとしています。非同期操作は問題なく機能しますが、別のスレッドが所有しているため、解決された名前をリストボックスに追加できません。この問題を回避して、解決した名前をリストボックスに追加するにはどうすればよいですか。

これが私がこれまでにしたことです

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

目的は、から実行を継続しGetHostEntryCallback(内で匿名である可能性がありますAsyncDNSResolver)、別のイベントを発生させてデータを呼び出し元に返すことです。これは、利用可能な非同期プログラミングモデルの性質です(C#5より前)。この場合、終了するまでに利用AsyncDNSResolverできないため、戻るstringことはできません。

あなたの選択は以下に帰着します:

  1. から文字列を返そうとするのではなく、イベントを発生させる(または別のコールバックを呼び出す)ことで非同期を受け入れますAsyncDNSResolver
  2. asyncメソッドの使用を停止し、Dns.GetHostEntry代わりにブロッキングを使用してください。
于 2012-10-23T10:18:32.777 に答える
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 に答える