C#,最大化线程并发 [英] C#, Maximize Thread Concurrency

查看:102
本文介绍了C#,最大化线程并发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Google和社区的帮助下,我能够建立一套不错的方法,使我可以异步调用一个函数.此功能正在测试远程主机属性,因此大多数时间处于空闲状态.因此,我想最大化启动的并发线程数,以便可以在最短的时间内处理所有调用.

With the help of Google and community, I was able to build a nice set of methods allowing me to asynchronously call a function. This function is testing remote host properties, so it is idling most of the time. For this reason I would like to maximize the number of concurrent threads launched such that all calls can be processed in the minimum amount of time.

这是我到目前为止的代码:

Here is the Code I have so far:

// Check remote host connectivity
public static class CheckRemoteHost
{

    // Private Class members
    private static bool AllDone     = false;
    private static object lockObj   = new object();
    private static List<string> IPs;


    // Wrapper: manage async method <Ping>
    public static List<string> Ping(HashSet<string> IP_Ports, int TimeoutInMS = 100)
    {// async worker method:  check remote host via <Ping>

        // Locals
        IPs = new List<string>();

        // Perform remote host check
        AllDone = false;
        Ping_check(IP_Ports, TimeoutInMS);
        while (!AllDone) { CommonLib.Utils.ApplicationWait(10, 10); }

        // Finish
        return IPs;
    }
    private static async void Ping_check(HashSet<string> IP_Ports, int timeout)
    {
        // Locals
        var tasks = new List<Task>();

        // Build task-set for parallel Ping checks
        foreach (string host in IP_Ports)
        {
            var task = PingAndUpdateAsync(host, timeout);
            tasks.Add(task);
        }

        // Start execution queue
        await Task.WhenAll(tasks).ContinueWith(t =>
        {
            AllDone = true;
        });

    }
    private static async Task PingAndUpdateAsync(string ip, int timeout)
    {

        // Locals
        System.Net.NetworkInformation.Ping ping;
        System.Net.NetworkInformation.PingReply reply;

        try
        {
            ping    = new System.Net.NetworkInformation.Ping();
            reply   = await ping.SendPingAsync(ip, timeout);

            if(reply.Status == System.Net.NetworkInformation.IPStatus.Success)
            {
                lock (lockObj)
                {
                    IPs.Add(ip);
                }
            }
        }
        catch
        {
            // do nothing
        }
    }

}// end     public static class CheckRemoteHost

此代码已进行了广泛的测试,该代码似乎稳定且可靠地报告了活动主机.话虽如此,我知道它一次只产生8个线程(=我的测试机器上逻辑核心的数量).

This code is tested quite extensively, and the code seems stable and reliably report live hosts. Having said that, I know that it only spawns 8 threads at a time (= number of logical core on my test machine).

代码的关键部分是这样:

The key portion of the code is this:

// Start execution queue
await Task.WhenAll(tasks).ContinueWith(t =>
{
    AllDone = true;
});

在这里我想将并发启动的线程数增加/最大化到每个内核25个左右(请记住线程作业是99%空闲的).

This is where I would like to increase/ maximize the number of concurrently launched threads to something like 25 per core (remember the thread job is 99% idle).

到目前为止,我的线程并发研究提出了显式线程和Parallel.For方法.但是,它们似乎具有产生不超过8个线程的相同缺点.

So far, my thread concurrency research has brought up the explicit thread and Parallel.For approaches. However, these seem to have the same shortcoming of spawning no more than 8 threads.

任何帮助将不胜感激,所以在此先非常感谢大家的光临!

Any help would be very much appreciated, so thank you very much in advance everyone for looking!

推荐答案

您正在用自己的代码使生活变得艰难.有很多不必要的工作,而且您正在共享静态字段,如果在第一个运行时再次调用Ping,则会导致代码失败.

You're making your life hard with the code you have. It's got a lot of plumbing that isn't needed and you're sharing static fields that would cause your code to fail if you called Ping a second time while the first one is running.

您需要摆脱所有这些东西.

You need to get rid of all of that stuff.

我建议使用Microsoft的Reactive Framework-仅使用NuGet"System.Reactive",然后将using System.Reactive.Linq;添加到您的代码中.然后,您可以执行以下操作:

I'd suggest using Microsoft's Reactive Framework - just NuGet "System.Reactive" and add using System.Reactive.Linq; to your code. Then you can do this:

public static class CheckRemoteHost
{
    public static IList<string> Ping(HashSet<string> IP_Ports, int TimeoutInMS = 100)
    {
        var query =
            from host in IP_Ports.ToObservable()
            from status in Observable.FromAsync(() => PingAsync(host, TimeoutInMS))
            where status
            select host;

        return query.ToList().Wait();
    }

    private static async Task<bool> PingAsync(string ip, int timeout)
    {
        try
        {
            var ping = new System.Net.NetworkInformation.Ping();
            var reply = await ping.SendPingAsync(ip, timeout);

            return reply.Status == System.Net.NetworkInformation.IPStatus.Success;
        }
        catch
        {
            return false;
        }
    }
}

就是这样.这就是您需要的所有代码.它会自动最大限度地利用线程来完成工作.

That's it. That's all of the code you need. It's automatically maximising the thread use to get the job done.

这篇关于C#,最大化线程并发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆