C# 一次最多3个线程的限制

C# 一次最多3个线程的限制,c#,multithreading,.net-4.0,task-parallel-library,task,C#,Multithreading,.net 4.0,Task Parallel Library,Task,我有以下代码从各种网站下载html字符串 class Program { static void Main(string[] args) { List<string> URLsToProcess = new List<string>() { "http://www.microsoft.com", "http://www.stackoverflow.com",

我有以下代码从各种网站下载html字符串

class Program
{
    static void Main(string[] args)
    {
        List<string> URLsToProcess = new List<string>()
        {
            "http://www.microsoft.com",
            "http://www.stackoverflow.com",
            "http://www.google.com",
            "http://www.apple.com",
            "http://www.ebay.com",
            "http://www.oracle.com",
            "http://www.gmail.com",
            "http://www.amazon.com",
            "http://www.yahoo.com",
            "http://www.msn.com"
        };



        List<Task<string>> tURLs = new List<Task<string>>();

        foreach (string url in URLsToProcess)
        {
            Task<string> t = DownloadStringAsTask(new Uri(url));
            tURLs.Add(t);
        }

        Console.WriteLine("waiting now");

        Task.WaitAll(tURLs.ToArray());

        Console.WriteLine("download all done");
        foreach (Task<string> t in tURLs)
            Console.WriteLine(t.Result);
    }


    static Task<string> DownloadStringAsTask(Uri address)
    {
        TaskCompletionSource<string> tcs =
          new TaskCompletionSource<string>();
        WebClient client = new WebClient();
        client.DownloadStringCompleted += (sender, args) =>
        {
            if (args.Error != null)
                tcs.SetException(args.Error);
            else if (args.Cancelled)
                tcs.SetCanceled();
            else
                tcs.SetResult(args.Result);
        };
        client.DownloadStringAsync(address);
        return tcs.Task;
    }
}
类程序
{
静态void Main(字符串[]参数)
{
List URLsToProcess=新列表()
{
"http://www.microsoft.com",
"http://www.stackoverflow.com",
"http://www.google.com",
"http://www.apple.com",
"http://www.ebay.com",
"http://www.oracle.com",
"http://www.gmail.com",
"http://www.amazon.com",
"http://www.yahoo.com",
"http://www.msn.com"
};
List tURLs=新列表();
foreach(URLsToProcess中的字符串url)
{
Task t=DownloadStringAsTask(新Uri(url));
添加(t);
}
Console.WriteLine(“正在等待”);
Task.WaitAll(tURLs.ToArray());
Console.WriteLine(“下载全部完成”);
foreach(任务t在tURLs中)
控制台写入线(t.Result);
}
静态任务下载StringAstask(Uri地址)
{
TaskCompletionSource tcs=
新建TaskCompletionSource();
WebClient客户端=新的WebClient();
client.DownloadStringCompleted+=(发送方,参数)=>
{
如果(args.Error!=null)
tcs.SetException(参数错误);
否则如果(参数已取消)
setCancelled();
其他的
tcs.SetResult(args.Result);
};
client.DownloadStringAsync(地址);
返回tcs.Task;
}
}
使用此代码可以启动10个不同的线程,从所有10个不同的URL下载数据。我想限制它一次最多3个线程。任何其他请求都应该等待其中一个线程被释放。关于如何添加此限制,您有什么想法吗?

请查看vs。您可以在此处使用并行LINQ:

var URLsToProcess = new List<string>
                    {
                        "http://www.microsoft.com",
                        "http://www.stackoverflow.com",
                        "http://www.google.com",
                        "http://www.apple.com",
                        "http://www.ebay.com",
                        "http://www.oracle.com",
                        "http://www.gmail.com",
                        "http://www.amazon.com",
                        "http://www.yahoo.com",
                        "http://www.msn.com"
                    };

Console.WriteLine("waiting now");

string[] tURLs = URLsToProcess
    .AsParallel()
    .WithDegreeOfParallelism(3)
    .Select(uri => this.DownloadStringAsTask(new Uri(uri)).Result)
    .ToArray();

Console.WriteLine("download all done");
foreach (string t in tURLs)
{
    Console.WriteLine(t);
}
var URLsToProcess=新列表
{
"http://www.microsoft.com",
"http://www.stackoverflow.com",
"http://www.google.com",
"http://www.apple.com",
"http://www.ebay.com",
"http://www.oracle.com",
"http://www.gmail.com",
"http://www.amazon.com",
"http://www.yahoo.com",
"http://www.msn.com"
};
Console.WriteLine(“正在等待”);
字符串[]tURLs=URLsToProcess
.天冬酰胺()
.平行度(3)
.Select(uri=>this.DownloadStringAsTask(新uri(uri)).Result)
.ToArray();
Console.WriteLine(“下载全部完成”);
foreach(图尔中的t串)
{
控制台写入线(t);
}

您可以使用SemaphoreSlim类来限制一次执行的线程数。 班级计划 {

static void Main(字符串[]args)
{
List URLsToProcess=新列表()
{
"http://www.microsoft.com",
"http://www.stackoverflow.com",
"http://www.google.com",
"http://www.apple.com",
"http://www.ebay.com",
"http://www.oracle.com",
"http://www.gmail.com",
"http://www.amazon.com",
"http://www.yahoo.com",
"http://www.msn.com"
};
SemaphoreSlim ss=新的SemaphoreSlim(3);//一次限制3个线程
List tURLs=新列表();
foreach(URLsToProcess中的字符串url)
{
//Task t=DownloadStringAsTask(新Uri(url));
//添加(t);
tURLs.Add((任务)Task.Run(()=>
{
下载StringAstask(新Uri(url));
ss.Release();
}));
}
Console.WriteLine(“正在等待”);
Task.WaitAll(tURLs.ToArray());
Console.WriteLine(“下载全部完成”);
foreach(任务t在tURLs中)
控制台写入线(t.Result);
Console.ReadLine();
}
静态任务下载StringAstask(Uri地址)
{
TaskCompletionSource tcs=
新建TaskCompletionSource();
WebClient客户端=新的WebClient();
client.DownloadStringCompleted+=(发送方,参数)=>
{
如果(args.Error!=null)
tcs.SetException(参数错误);
否则如果(参数已取消)
setCancelled();
其他的
tcs.SetResult(args.Result);
};
client.DownloadStringAsync(地址);
返回tcs.Task;
}
}

A
任务
不是
线程
,如果你想控制线程,你应该使用
线程池
,你应该使用信号量来限制这个限制。你想建立你自己的线程池吗?@doctor:一点也不。据我所知,任务内部使用线程池中的线程。我只想将并行线程的最大数量限制为3。任务!=线@johnsmithURL引发异常时会发生什么情况?
    static void Main(string[] args)
    {

        List<string> URLsToProcess = new List<string>()
        {
            "http://www.microsoft.com",
            "http://www.stackoverflow.com",
            "http://www.google.com",
            "http://www.apple.com",
            "http://www.ebay.com",
            "http://www.oracle.com",
            "http://www.gmail.com",
            "http://www.amazon.com",
            "http://www.yahoo.com",
            "http://www.msn.com"
        };

        SemaphoreSlim ss = new SemaphoreSlim(3); //limit 3 threads at a time

        List<Task<string>> tURLs = new List<Task<string>>();


        foreach (string url in URLsToProcess)
        {
            //Task<string> t = DownloadStringAsTask(new Uri(url));
            //tURLs.Add(t);
            tURLs.Add((Task<string>)Task.Run(() =>
            {
                DownloadStringAsTask(new Uri(url));
                ss.Release();
            }));
        }

        Console.WriteLine("waiting now");

        Task.WaitAll(tURLs.ToArray());

        Console.WriteLine("download all done");
        foreach (Task<string> t in tURLs)
            Console.WriteLine(t.Result);

        Console.ReadLine();
    }



    static Task<string> DownloadStringAsTask(Uri address)
    {
        TaskCompletionSource<string> tcs =
          new TaskCompletionSource<string>();
        WebClient client = new WebClient();
        client.DownloadStringCompleted += (sender, args) =>
        {
            if (args.Error != null)
                tcs.SetException(args.Error);
            else if (args.Cancelled)
                tcs.SetCanceled();
            else
                tcs.SetResult(args.Result);
        };

        client.DownloadStringAsync(address);

        return tcs.Task;
    }
}