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 回答