C#紧凑框架:多线程导致延迟?

时间:2009-12-24 06:59:46

标签: c# compact-framework

在我的移动应用中,我想从链接的arraylist加载所有图像。对于每个链接,我创建一个线程并制作httpwebrequest。问题是我的应用程序运行不顺畅。每次我创建新线程和线程完成时似乎都会延迟(当线程完成时我会将下载img绘制到背景上)。这是我的代码:

            for (int i = 0; i < NumbersOfImg; i++)
            {
                if (i < ImgObjArr.Count)
                {
                    ThreadStart myThread = new ThreadStart(getUrlImg);
                    Thread t = new Thread(myThread);
                    t.Start();
                }
            }


     private void getUrlImg()
     {
            MyImage mycurrentImg = (MyImage)ImgObjArr[currentMyImg];
            if (currentMyImg < ImgObjArr.Count - 1)
                currentMyImg++;
            myRequest = (HttpWebRequest)WebRequest.Create(mycurrentImg.ImageLink);
            myResponse = (HttpWebResponse)myRequest.GetResponse();

            Stream ImgStream = myResponse.GetResponseStream();
            mycurrentImg.FullImg = new Bitmap(ImgStream);

            this.BeginInvoke(new EventHandler(ImageUpdate));
    }

和方法ImageUpdate()将绘制图像。当应用程序导航到下一行时,我将创建多个线程以继续进行webrequest。当旧线程未完成但我创建新线程时会发生延迟。那么有什么建议为什么我的应用程序有延迟?提前谢谢。

2 个答案:

答案 0 :(得分:2)

缓慢的两个可能原因:

  1. 根据ImgObjArr.Count的值,问题中的代码可能会创建大量线程,所有线程都会占用CPU。线程代码本身几乎无害 - 它们等待HTTP响应返回。但是,如果同时运行大量数据,则可能会出现CPU峰值,从而降低UI的速度。当发送请求时,以及响应开始返回并且代码创建Bitmap对象时,可能会发生这种情况。上下文切换也有成本。

    什么数量的线程太高取决于所讨论的CPU的功率。鉴于这是一个紧凑框架问题,那将是频谱的低端问题。您可能需要考虑将后台线程数限制为固定池大小。 2-4之间的某些数字可能是正确的。请注意,如果框架无论如何都限制了传出连接的数量,那么您将无法从更多线程中获益。 (应该有框架设置的默认限制,我相信有2个连接,您可以更改。操作系统也可以设置限制)

  2. ImageUpdate中的代码在应用程序的UI线程中执行。任何时间都没有时间处理输入。这直接导致UI延迟。如果有任何代码可以推送到后台线程,那将是一个值得的练习。如果所有可以移动到后台的代码都已移动,减少后台线程的数量仍然会有所帮助,因为这样可以减少多个位图同时命中UI线程并创建链式延迟的可能性。

    < / LI>

答案 1 :(得分:2)

创建新线程实际上非常慢,并且您在单个处理器系统上一次运行的线程越多,每个线程在启动后运行所需的时间就越长。你真正需要的是将线程的数量限制在合理的范围内,并且只启动线程一次,然后重新使用它们。

实际上,微软已经完成了为这类任务管理线程池的所有艰苦工作,它被称为线程池。您可以按如下方式使用它:

for (int i = 0; i < NumbersOfImg; i++)
{
    if (i < ImgObjArr.Count)
    {
        ThreadPool.QueueUserWorkItem(getUrlImg)
    }
}


 private void getUrlImg(object state)
 {
     MyImage mycurrentImg = (MyImage)ImgObjArr[currentMyImg];
     if (currentMyImg < ImgObjArr.Count - 1)
         currentMyImg++;
     myRequest = (HttpWebRequest)WebRequest.Create(mycurrentImg.ImageLink);
     myResponse = (HttpWebResponse)myRequest.GetResponse();

     Stream ImgStream = myResponse.GetResponseStream();
     mycurrentImg.FullImg = new Bitmap(ImgStream);

     this.BeginInvoke(new EventHandler(ImageUpdate));
}