我用多线程写的代码,为什么和单线程速度差不多呢?

泡泡龙 2014-01-16 12:06:02
代码如下:

Task[] tasks = new Task[end - start + 1];
for (int i = start; i <= end; i++)
{
//tasks[i - start] = Task.Factory.StartNew(() =>
tasks[i - start] = new Task(() =>
{
if (importCts.IsCancellationRequested)
{
//close you window
}
else
{
download(token, this.tbxDir.Text, end);
}
}, ctstoken);
tasks[i - start].ContinueWith((a) => { info1(); });
tasks[i - start].Start();
}

Task.WaitAll(tasks);

download(token, this.tbxDir.Text, end)是使用HttpWebRequest下载不同id代码的文件。

我用多线程写的代码,为什么和单线程速度差不多呢?还不如我人工多开下载快呢?

为什么呢?貌似task没起啥作用,还是windows对一个进程下载文件有数量限制?

...全文
365 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
泡泡龙 2014-01-16
  • 打赏
  • 举报
回复
顺便问个问题,我用for语句里面的i作为参数给download,结果发现所有的线程最后WaitAll运行的时候,执行的i都是一个数---> i的终值+1。 这是为啥呢?难道task传递参数的时候,要等到wait的时候才真正传递数值吗?
泡泡龙 2014-01-16
  • 打赏
  • 举报
回复
调试发现task好像启动线程很慢呀,50个线程启动要等半天 我把download()换成下面的代码,居然要24秒。不加延时也要2~3秒。 private void delay(int ms) { id_idx++; Thread.Sleep(3000); Thread ts = new Thread(new ThreadStart(info)); ts.IsBackground = true; ts.Start(); id_idx1++; }
泡泡龙 2014-01-16
  • 打赏
  • 举报
回复
引用 1 楼 caozhy 的回复:
download()怎么写的,如果有lock之类的锁定或者control.invoke等等的同步,那么就会阻塞住。
看着也没啥呀,除非是写文件阻塞了?
private void downloadsgf(string token, string dirpath, int max)
        {

            int i = id_idx;
            if (id_idx > max)
            {
                importCts.Cancel();
                id_idx1++;
                return;
            }
            id_idx++;

            Thread ts = new Thread(new ThreadStart(info));
            ts.IsBackground = true;
            ts.Start();

            //Console.Beep(1000, 100);
            //Debug.WriteLine(i.ToString());
            string postString = @"pid=" + i.ToString() +
                                @"&csrfmiddlewaretoken=" + token;

            string downurl1 = @"******************";
            string responsetext = string.Empty;
            HttpStatusCode statuscode = HttpHelper.GetResponse(ref responsetext, downurl1, "POST", postString);
            if (!responsetext.Contains(@"/"))
            {
                resultmsg += @"返回文件链接错误" + i + " responsetext:" + responsetext + Environment.NewLine;
                id_idx1++;
                return;
            }
            string[] aryfilename = responsetext.Split('\"');
            string filename = aryfilename[aryfilename.Length - 2];
            //Clipboard.SetDataObject(responsetext, true);
            if (filename == "result")
            {
                resultmsg += @"文件名解析错误:" + i + " " + filename + Environment.NewLine;
                return;
            }
            string downurl2 = @"**************" + Uri.EscapeUriString(filename);

            statuscode = HttpHelper.GetResponse(ref responsetext, downurl2, "Get", string.Empty);

            if (statuscode == HttpStatusCode.OK)
            {
                int idx = filename.LastIndexOf('/');
                filename = filename.Substring(idx + 1, filename.Length - idx - 1);
                filename = filterFilename(filename);
                FileStream fs = new FileStream(dirpath + filename, FileMode.Create);
                StreamWriter sw = new StreamWriter(fs);
                sw.Write(responsetext);  //开始写入
                sw.Flush();              //清空缓冲区
                sw.Close();              //关闭流
                fs.Close();
                count_success++;
            }
            else
            {
                resultmsg += i + Environment.NewLine;
            }
            id_idx1++;
        }
threenewbee 2014-01-16
  • 打赏
  • 举报
回复
download()怎么写的,如果有lock之类的锁定或者control.invoke等等的同步,那么就会阻塞住。
泡泡龙 2014-01-16
  • 打赏
  • 举报
回复
改成Parallel.For了 Task task=Task.Factory.StartNew(() => Parallel.For(start, end+1, (i) => download(i)) ).ContinueWith((a) => { over(); }); 下载1000个,看线程能加到600左右
xuqing19830921 2014-01-16
  • 打赏
  • 举报
回复
PS:跟机器硬件配置,同样有关
泡泡龙 2014-01-16
  • 打赏
  • 举报
回复
引用 5 楼 LargeSkyMensk 的回复:
其它的不做评论。 但是你使用lamda表达式的时候,就应该了解它的一些负面影响。 其中之一:就是在for循环中,不在能lamda表达式中使用一些变量。 你可以使用IL反汇编生成的代码出来看一下,就懂了。
百度没找到相关资料,哪里有能否推荐一下,谢谢
泡泡龙 2014-01-16
  • 打赏
  • 举报
回复
System.Threading.Tasks中的类被统称为任务并行库(Task Parallel Library,TPL),TPL使用CLR线程池把工作分配到CPU,并能自动处理工作分区、线程调度、取消支持、状态管理以及其他低级别的细节操作,极大地简化了多线程的开发。 注意:TPL比Thread更具智能性,当它判断任务集并没有从并行运行中受益,就会选择按顺序运行。但并非所有的项目都适合使用并行开发,创建过多并行任务可能会损害程序的性能,降低运行效率。 莫非是这个原因? 我把代码改成这样,速度能快一倍,但也没像想象的那样并发一二十个同时进行 Action[] actions = new Action[end - start + 1]; for (int i = start; i <= end; i++) { actions[i - start] = () => download(); } Parallel.Invoke(actions);
largeskymengsk 2014-01-16
  • 打赏
  • 举报
回复
其它的不做评论。 但是你使用lamda表达式的时候,就应该了解它的一些负面影响。 其中之一:就是在for循环中,不在能lamda表达式中使用一些变量。 你可以使用IL反汇编生成的代码出来看一下,就懂了。

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧