[英]Parallel async operation, how to “kill” one after a timeout?
I have a program that I use to get some data from my network through SNMP. 我有一个程序,可用于通过SNMP从网络中获取一些数据。 I use last .NET and SharpSnmp library . 我使用最后一个.NET和SharpSnmp库 。 I realize a ForEachAsync method like exposed in this post . 我实现了一个ForEachAsync方法,就像在这篇文章中公开的那样。 So I can execute snmp request in parallel (and elaborate the response), creating a Task for each device in my list. 因此,我可以并行执行snmp请求(并详细说明响应),为列表中的每个设备创建一个Task。 It works, but if a device doesn't reply for some reason my program get stuck. 它可以工作,但是如果设备由于某种原因没有响应,我的程序就会卡住。 So I need to manage some sort of timeout to "kill" the async function exposed by the library. 因此,我需要管理某种超时以“杀死”该库公开的异步功能。 That is the function I'm calling in my foreachAsync: 那就是我在foreachAsync中调用的函数:
public static async Task<Tuple<string, List<Variable>, Exception>>
GetAsync(string ip, IEnumerable<string> vars, int timeout = 5000)
{
try
{
IPAddress agentIp;
bool parsed = IPAddress.TryParse(ip, out agentIp);
if (!parsed)
{
foreach (IPAddress address in
Dns.GetHostAddresses(ip).Where(address => address.AddressFamily == AddressFamily.InterNetwork))
{
agentIp = address;
break;
}
if (agentIp == null)
throw new Exception("Impossibile inizializzare la classe CGesSnmp senza un indirizzo IP valido");
}
IPEndPoint receiver = new IPEndPoint(agentIp, LOCAL_PORT);
VersionCode version = VersionCode.V2;
string community = "public";
List<Variable> vList = new List<Variable>();
foreach (string s in vars)
vList.Add(new Variable(new ObjectIdentifier(s)));
// This is the function I want to "stop" or "kill" in some way
List<Variable> result = (List<Variable>)await Messenger.GetAsync(version, receiver, new OctetString(community), vList);
return new Tuple<string, List<Variable>, Exception>(ip, result, null);
}
catch (Exception ex)
{
return new Tuple<string, List<Variable>, Exception>(ip, null, ex);
}
}
If method supports TaskCancellationToken
如果方法支持TaskCancellationToken
public static async Task<Tuple<string, List<Variable>, Exception>>
GetAsync(string ip, IEnumerable<string> vars, int timeout = 5000)
{
try
{
IPAddress agentIp;
bool parsed = IPAddress.TryParse(ip, out agentIp);
if (!parsed)
{
foreach (IPAddress address in
Dns.GetHostAddresses(ip).Where(address => address.AddressFamily == AddressFamily.InterNetwork))
{
agentIp = address;
break;
}
if (agentIp == null)
throw new Exception("Impossibile inizializzare la classe CGesSnmp senza un indirizzo IP valido");
}
IPEndPoint receiver = new IPEndPoint(agentIp, LOCAL_PORT);
VersionCode version = VersionCode.V2;
string community = "public";
List<Variable> vList = new List<Variable>();
foreach (string s in vars)
vList.Add(new Variable(new ObjectIdentifier(s)));
// This is the function I want to "stop" or "kill" in some way
CancellationTokenSource cancel = new CancellationTokenSource(TimeSpan.FromSeconds(timeout));
List<Variable> result = (List<Variable>)await Messenger.GetAsync(version, receiver, new OctetString(community), vList, cancel.Token);
return new Tuple<string, List<Variable>, Exception>(ip, result, null);
}
catch (Exception ex)
{
return new Tuple<string, List<Variable>, Exception>(ip, null, ex);
}
}
Or Else 要不然
public static Task<Tuple<string, List<Variable>, Exception>>
GetAsync(string ip, IEnumerable<string> vars, int timeout = 5000){
TaskCompletionSource<Tuple<string,List<Variable>>> taskSource =
new TaskCompletionSource<Tuple<string,List<Variable>>>();
Task.Run(async ()=> {
var result = await GetAsync(ip,vars);
taskSource.TrySetResult(result);
});
Task.Run(async ()=>{
await Task.Delay(TimeSpan.FromSeconds(timeout));
taskSource.TrySetCancelled();
});
return taskSource.Task;
}
private static async Task<Tuple<string, List<Variable>, Exception>>
_GetAsync(string ip, IEnumerable<string> vars)
{
try
{
IPAddress agentIp;
bool parsed = IPAddress.TryParse(ip, out agentIp);
if (!parsed)
{
foreach (IPAddress address in
Dns.GetHostAddresses(ip).Where(address => address.AddressFamily == AddressFamily.InterNetwork))
{
agentIp = address;
break;
}
if (agentIp == null)
throw new Exception("Impossibile inizializzare la classe CGesSnmp senza un indirizzo IP valido");
}
IPEndPoint receiver = new IPEndPoint(agentIp, LOCAL_PORT);
VersionCode version = VersionCode.V2;
string community = "public";
List<Variable> vList = new List<Variable>();
foreach (string s in vars)
vList.Add(new Variable(new ObjectIdentifier(s)));
// This is the function I want to "stop" or "kill" in some way
List<Variable> result = (List<Variable>)await Messenger.GetAsync(version, receiver, new OctetString(community), vList);
return new Tuple<string, List<Variable>, Exception>(ip, result, null);
}
catch (Exception ex)
{
return new Tuple<string, List<Variable>, Exception>(ip, null, ex);
}
}
Task<[whatever type GetAsync returns]> messengerTask = Messenger.GetAsync(version, receiver, new OctetString(community), vList);
if (await Task.WhenAny(messengerTask, Task.Delay(timeout)) == messengerTask)
{
//GetAsync completed within timeout. Access task's result using
// messengerTask.Result. You can also check if the task RanToCompletion.
}
else
{
//timeout
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.