C# 在BeginXXX和EndXXX方法中使用AsyncWaitHandle
我想调用一个异步操作,该操作返回一个C# 在BeginXXX和EndXXX方法中使用AsyncWaitHandle,c#,asynchronous,dns,C#,Asynchronous,Dns,我想调用一个异步操作,该操作返回一个IAsyncResult对象,特别是System.Net.Dns类的GetHostEntry方法 我知道我应该调用IAsyncResult的AsyncWaitHandle属性的WaitOne方法,等待操作完成,但显然我错了,因为这段代码不起作用: using System; using System.Net; static class Program { class GetHostEntryState { public IPHost
IAsyncResult
对象,特别是System.Net.Dns
类的GetHostEntry
方法
我知道我应该调用IAsyncResult
的AsyncWaitHandle
属性的WaitOne
方法,等待操作完成,但显然我错了,因为这段代码不起作用:
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");
}
}
}
使用
ManualResetEvent
对象执行同步。有必要吗?如果是这样,那么这里的AsyncWaitHandle
属性有什么用?因为我想要的是一个带有超时的GetHostEntry,所以我提出了这个解决方案,如果我理解正确的话,应该可以避免资源泄漏,因为最终还是会调用EndGetHostEntry操作
我在这里分享它,以防它对其他人有用:)
从你所看到的,你可以看出这是必要的。在线程竞争中,AsyncWaitHandle.WaitOne()通常在回调之前完成。通过调用异步方法但同步等待它,您陷入了这个困境。可能是因为你想要暂停。下一件你必须担心的事情是,当你有一个超时时间时,你是如何清理的。@HansPassant:那么AsyncWaitHandle.WaitOne()的用途是什么呢?我仍然不明白…它的目的是告诉您何时可以调用EndXxx()方法而不阻塞它。如果没有回调,则在WaitOne()调用后调用EndGetHostEntry(),这将起作用。但是因为超时,你付不起。不打电话会导致资源泄漏。@HansPassant:谢谢,我想我现在知道了。
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
}