0

IAsyncResultオブジェクト、特にクラスのGetHostEntryメソッドを返す非同期操作を呼び出したいと思います。System.Net.Dns

のプロパティのWaitOneメソッドを呼び出して、操作が完了するまで特定のタイムアウトで待機する必要があることは理解していましたが、このコードが機能しないため、明らかに間違っています。AsyncWaitHandleIAsyncResult

using System;
using System.Net;

static class Program {

    class GetHostEntryState {
        public IPHostEntry Value {
            get;
            set;
        }
    }

    static void Main(string[] args) {
        string hostName = "somehost";
        int timeout = 1000;

        var state = new GetHostEntryState();
        var asyncResult = Dns.BeginGetHostEntry(hostName, ar => {
            ((GetHostEntryState)ar.AsyncState).Value = Dns.EndGetHostEntry(ar);
        }, state);
        if (asyncResult.AsyncWaitHandle.WaitOne(timeout) && asyncResult.IsCompleted) {
            if (state.Value == null) {
                // we always hit this condition
                Console.WriteLine("state.Value == null");
                return;
            }
            foreach (var address in state.Value.AddressList) {
                Console.WriteLine(address);
            }
        } else {
            Console.WriteLine("timed out");
        }
    }
}

msdnの例では、ManualResetEventオブジェクトを使用して同期を行います。それは必要ですか?もしそうなら、AsyncWaitHandleここのプロパティの用途は何ですか?

4

1 に答える 1

1

私が欲しかったのはタイムアウト付きのGetHostEntryだったので、このソリューションを思いつきました。正しく理解していれば、最終的にEndGetHostEntry操作が呼び出されるため、リソースのリークを回避する必要があります。

他の誰かに役立つ場合に備えて、ここで共有しています:)

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;

public sealed class HostEntryTimeout {

    public IPHostEntry HostEntry {
        get;
        private set;
    }

    string _hostName;
    int _timeoutInMilliseconds;
    ManualResetEvent _getHostEntryFinished;

    public HostEntryTimeout(string alias, int timeoutInMilliseconds) {
        _hostName = alias;
        _timeoutInMilliseconds = timeoutInMilliseconds;
        _getHostEntryFinished = new ManualResetEvent(false);
    }

    /// <summary>
    /// Gets the IPHostEntry.
    /// </summary>
    /// <returns>True if successful, false otherwise.</returns>
    public bool GetHostEntry() {
        _getHostEntryFinished.Reset();
        Dns.BeginGetHostEntry(_hostName, GetHostEntryCallback, null);
        if (!_getHostEntryFinished.WaitOne(_timeoutInMilliseconds)) {
            return false;
        }
        if (HostEntry == null) {
            return false;
        }
        return true;
    }

    void GetHostEntryCallback(IAsyncResult asyncResult) {
        try {
            HostEntry = Dns.EndGetHostEntry(asyncResult);
        } catch (SocketException) {
        }
        _getHostEntryFinished.Set();
    }
}

次に、次のように使用できます。

var hostEntryTimeout = new HostEntryTimeout("somehost", 1000);
if (hostEntryTimeout.GetHostEntry()) {
    // success, do something with the hostEntryTimeout.HostEntry object
}
于 2013-02-06T13:10:07.593 に答える