简体   繁体   English

我的代码(SendPingAsync)有什么问题

[英]What is wrong with my Code (SendPingAsync)

Im writing a C# Ping-Application. 我正在编写一个C# Ping应用程序。 I started with a synchronous Ping-method, but I figurred out that pinging several server with one click takes more and more time. 我从synchronous Ping方法开始,但是我发现一次单击即可ping多个服务器会花费越来越多的时间。 So I decided to try the asynchronous method. 因此,我决定尝试asynchronous方法。

Can someone help me out? 有人可以帮我吗?

public async Task<string> CustomPing(string ip, int amountOfPackets, int sizeOfPackets)
{
    // timeout
    int Timeout = 2000;
    // PaketSize logic
    string packet = "";
    for (int j = 0; j < sizeOfPackets; j++)
    {
        packet += "b";
    };
    byte[] buffer = Encoding.ASCII.GetBytes(packet);
    // time-var
    long ms = 0;
    // Main Method
    using (Ping ping = new Ping())
        for (int i = 0; i < amountOfPackets; i++)
        {
            PingReply reply = await ping.SendPingAsync(ip, Timeout, buffer);
            ms += reply.RoundtripTime;
        };
    return (ms / amountOfPackets + " ms");
};

I defined a "Server"-Class (Ip or host, City, Country). 我定义了“服务器”类(Ip或主机,城市,国家/地区)。

Then I create a "server"-List: 然后创建一个“服务器”列表:

List<Server> ServerList = new List<Server>()
            {
                new Server("www.google.de", "Some City,", "Some Country")
};

Then I loop through this list and I try to call the method like this: 然后,我遍历此列表,并尝试调用如下方法:

foreach (var server in ServerList)
ListBox.Items.Add("The average response time of your custom server is: " + server.CustomPing(server.IP, amountOfPackets, sizeOfPackets));

Unfortunately, this is much more competitive than the synchronous method, and at the point where my method should return the value, it returns 不幸的是,这比synchronous方法更具竞争力,并且在我的方法应返回值的时候,它会返回

System.Threading.Tasks.Taks`1[System.string] System.Threading.Tasks.Taks`1 [System.string]

The class System.Threading.Tasks.Task<TResult> is a helper class for Multitasking. System.Threading.Tasks.Task<TResult>类是多任务处理的帮助程序类。 While it resides in the Threading Namespace, it works for Threadless Multitasking just as well. 虽然它位于线程命名空间中,但它也适用于无线程多任务处理。 Indeed if you see a function return a task, you can usually use it for any form of Multitasking. 确实,如果看到函数返回任务,通常可以将其用于任何形式的多任务处理。 Tasks are very agnostic in how they are used. 任务的使用方式非常不可知。 You can even run it synchronously, if you do not mind that little extra overhead of having a Task doing not a lot. 如果您不介意让Task负担不大,那么甚至可以同步运行它。

Task helps with some of the most important rules/convetions of Multitasking: 任务有助于解决多任务的一些最重要的规则/要求:

  • Do not accidentally swallow exceptions. 不要意外地吞下异常。 Threadbase Multitasking is notoriously good in doing just that. 众所周知,线程库多任务处理就很好地做到了这一点。
  • Do not use the result after a cancelation 取消后请勿使用结果

It does that by throwing you exceptions in your face (usually the Aggregate one) if you try to access the Result Property when convention tells us you should not do that. 通过在约定告诉我们您不应该这样做时尝试访问Result属性 ,可以通过在您的脸上抛出异常(通常是聚合异常)来实现。

As well as having all those other usefull properties for Multitasking. 以及具有所有其他对多任务有用的属性。

since you have an async method it will return the task when it is called like this: 由于您有一个异步方法,因此调用该方法时将返回任务:

Task<string> task = server.CustomPing(server.IP, amountOfPackets, sizeOfPackets);

when you add it directly to your ListBox while concatenating it with a string it will use the ToString method, which by default prints the full class name of the object. 当您直接将其添加到ListBox并将其与字符串连接时,它将使用ToString方法,该方法默认情况下会打印对象的完整类名。 This should explaint your output: 这应该解释您的输出:

System.Threading.Tasks.Taks`1[System.string] System.Threading.Tasks.Taks`1 [System.string]

The [System.string] part actually tells you the return type of the task result. [System.string]部分实际上告诉您任务结果的返回类型。 This is what you want, and to get it you would need to await it! 这就是您想要的,要获得它,您需要等待它! like this: 像这样:

foreach (var server in ServerList)
   ListBox.Items.Add("The average response time of your custom server is: " + await server.CustomPing(server.IP, amountOfPackets, sizeOfPackets));

1) this has to be done in another async method and 1)这必须用另一种async方法来完成

2) this will mess up all the parallelity that you are aiming for. 2)这会搞乱您想要的所有并行性。 Because it will wait for each method call to finish. 因为它将等待每个方法调用完成。

What you can do is to start all tasks one after the other, collect the returning tasks and wait for all of them to finish. 您可以做的是一个接一个地启动所有任务,收集返回的任务,然后等待所有任务完成。 Preferably you would do this in an async method like a clickhandler: 最好使用异步方法(例如clickhandler)来执行此操作:

private async void Button1_Click(object sender, EventArgs e)
{
    Task<string> [] allTasks = ServerList.Select(server => server.CustomPing(server.IP, amountOfPackets, sizeOfPackets)).ToArray();
    // WhenAll will wait for all tasks to finish and return the return values of each method call
    string [] results = await Task.WhenAll(allTasks);
    // now you can execute your loop and display the results:
    foreach (var result in results)
    {
        ListBox.Items.Add(result);
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM