我需要创建一个应用程序,循环地ping多个地址。我在Stack Overflow上阅读了很多例子,并最终得到了可工作的代码:
public void Check(List<string> addresses)
{
List<Task<PingReply>> pingTasks = new List<Task<PingReply>>();
foreach (string address in addresses)
{
pingTasks.Add(PingAsync(address));
}
Task.Factory.ContinueWhenAll(pingTasks.ToArray(), _ => { }).ContinueWith(t =>
{
StringBuilder pingResult = new StringBuilder();
foreach (var pingTask in pingTasks)
{
pingResult.Append(pingTask.Result.Address);
pingResult.Append(" ");
pingResult.Append(pingTask.Result.Status);
pingResult.Append(" ");
pingResult.Append(pingTask.Result.RoundtripTime.ToString());
pingResult.Append(" \n");
}
Console.WriteLine(pingResult.ToString());
},
CancellationToken.None,
TaskContinuationOptions.None,
TaskScheduler.FromCurrentSynchronizationContext());
}
public static Task<PingReply> PingAsync(string address)
{
var tcs = new TaskCompletionSource<PingReply>();
using (Ping ping = new Ping())
{
ping.PingCompleted += (obj, sender) =>
{
tcs.SetResult(sender.Reply);
};
ping.SendAsync(address, new object());
}
return tcs.Task;
}
现在我需要将这段代码改为使用await和async,并且在循环中以间隔执行。这里我的问题开始了。我不知道在这种情况下如何使用async,我阅读了许多文章,但是我的代码仍然无法运行。您能逐步解释给我如何更改代码以与await配合使用吗?您能告诉我如何将其放入while循环中并执行间隔吗?我尝试将整个“Check”函数放入循环中,并在末尾添加Thread.Sleep(interval),但我有一种奇怪的感觉我正在做错误/低效的事情。我需要在1秒钟内ping 400个服务器。这是否可能?
此致敬礼
更新1: 到目前为止,我的代码如下:
using System;
using System.Collections.Generic;
using System.IO;
using System.Web;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Net.NetworkInformation;
using System.Linq;
namespace Pinging
{
class CheckPing
{
public async Task LoopAndCheckPingAsync(List<string> addresses)
{
while (true)
{
var ping = new Ping();
var pingTasks = addresses.Select(address => ping.SendPingAsync(address));
await Task.WhenAll(pingTasks);
StringBuilder pingResultBuilder = new StringBuilder();
foreach (var pingReply in pingTasks)
{
pingResultBuilder.Append(pingReply.Result.Address);
pingResultBuilder.Append(" ");
pingResultBuilder.Append(pingReply.Result.Status);
pingResultBuilder.Append(" ");
pingResultBuilder.Append(pingReply.Result.RoundtripTime.ToString());
pingResultBuilder.AppendLine();
}
Console.WriteLine(pingResultBuilder.ToString());
await Task.Delay(TimeSpan.FromMinutes(5));
}
}
}
}
以及调用:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pinging
{
public class Class1
{
static void Main()
{
List<string> addresses = new List<string>() { "www.google.pl", "212.77.100.101" };
CheckPing c = new CheckPing();
Task.Factory.StartNew(() => c.LoopAndCheckPingAsync(addresses));
Console.Read();
}
}
}
我尝试以不同的方式从主函数调用 LoopAndCheckPingAsync,但仍然出现了冻结。这是我的最后一次尝试。
编辑2: 我对应用程序性能进行了一些更改,现在我的代码看起来像这样:
using System;
using System.Collections.Generic;
using System.IO;
using System.Web;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Net.NetworkInformation;
using System.Linq;
namespace Pinging
{
class CheckPing
{
public async Task LoopAndCheckPingAsync(List<string> addresses)
{
while (true)
{
var pingTasks = addresses.Select(address =>
{
return new Ping().SendPingAsync(address);
});
await Task.WhenAll(pingTasks);
StringBuilder pingResultBuilder = new StringBuilder();
foreach (var pingReply in pingTasks)
{
pingResultBuilder.Append(pingReply.Result.Address);
pingResultBuilder.Append(" ");
pingResultBuilder.Append(pingReply.Result.Status);
pingResultBuilder.Append(" ");
pingResultBuilder.Append(pingReply.Result.RoundtripTime.ToString());
pingResultBuilder.AppendLine();
}
Console.WriteLine(pingResultBuilder.ToString());
Functions.counter++;
if (Functions.counter >= 100) break;
await Task.Delay(TimeSpan.FromSeconds(1));
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Pinging
{
public class Class1
{
static void Main()
{
List<string> addresses = Functions.Read(@"C:\Users\Adam\Desktop\addresses.csv");
Functions.start = DateTime.Now;
CheckPing c = new CheckPing();
c.LoopAndCheckPingAsync(addresses).Wait();
Console.WriteLine(Functions.counter);
Console.Read();
}
}
}
我正在使用从文件中读取的标准网站地址:
www.google.com
www.yahoo.com
www.live.com
www.msn.com
www.facebook.com
www.youtube.com
www.microsoft.com
www.wikipedia.org
www.myspace.com
www.ebay.com
www.aol.com
www.ask.com
www.craigslist.org
www.blogspot.com
www.answers.com
www.about.com
www.amazon.com
www.mapquest.com
www.windows.com
www.adobe.com
www.photobucket.com
www.wordpress.com
www.go.com
www.paypal.com
www.walmart.com
www.reference.com
www.cnn.com
www.twitter.com
www.imdb.com
www.flickr.com
www.att.com
www.cnet.com
www.irs.gov
www.whitepages.com
www.yellowpages.com
www.comcast.net
www.target.com
www.simplyhired.com
www.webmd.com
www.weather.com
www.blogger.com
www.bankofamerica.com
www.apple.com
www.chase.com
www.bizrate.com
www.hulu.com
www.merriam-webster.com
www.geocities.com
www.ehow.com
www.ezinearticles.com
编辑3:
现在一切运行良好,但这里有另一个问题需要处理。当我在5分钟内测试100000个ping时,会出现内存不足异常。是否有办法在处理此问题?也许分成块并销毁旧类?
编辑4:
错误内容:
编辑5:添加using语句后,我收到“没有足够的存储空间来处理此命令”的错误:System.OutOfMemoryException was unhandled HResult=-2147024882 Message=Exception of type 'System.OutOfMemoryException' was thrown. Source=mscorlib StackTrace: at System.Exception.Init() at System.InvalidOperationException..ctor(String message, Exception innerException) at System.Net.NetworkInformation.PingException..ctor(String message, Exception innerException) at System.Net.NetworkInformation.Ping.ContinueAsyncSend(Object state) at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() at System.Threading.ThreadPoolWorkQueue.Dispatch() at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
InnerException:
未处理的System.AggregateException异常 结果=-2146233088, 消息=发生一个或多个错误。 来源=mscorlib 堆栈跟踪: 在System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) 在System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken) 在System.Threading.Tasks.Task.Wait() 在Pinging.Class1.Main() 在System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) 在System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 在Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 在System.Threading.ThreadHelper.ThreadStart_Context(Object state) 在System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 在System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 在System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 在System.Threading.ThreadHelper.ThreadStart() 内部异常: System.Net.NetworkInformation.PingException 结果=-2146233079 消息=Ping请求期间发生异常。 来源=mscorlib 堆栈跟踪: 在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 在System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() 在Pinging.CheckPing.d__2.MoveNext() 内部异常: System.ApplicationException 结果=-2147024888 消息=没有足够的存储空间来处理此命令(来自HRESULT的异常:0x80070008) 来源=mscorlib 堆栈跟踪: 在System.Threading.ThreadPool.RegisterWaitForSingleObjectNative(WaitHandle waitHandle, Object state, UInt32 timeOutInterval, Boolean executeOnlyOnce, RegisteredWaitHandle registeredWaitHandle, StackCrawlMark& stackMark, Boolean compressStack) 在System.Threading.ThreadPool.RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, Object state, UInt32 millisecondsTimeOutInterval, Boolean executeOnlyOnce, StackCrawlMark& stackMark, Boolean compressStack) 在System.Threading.ThreadPool.RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, Object state, Int32 millisecondsTimeOutInterval, Boolean executeOnlyOnce) 在System.Net.NetworkInformation.Ping.InternalSend(IPAddress address, Byte[] buffer, Int32 timeout, PingOptions options, Boolean async) 在System.Net.NetworkInformation.Ping.ContinueAsyncSend(Object state) 内部异常: