Компактная структура C #: многопоточность вызывает задержку? - PullRequest
1 голос
/ 24 декабря 2009

В моем мобильном приложении я хочу загрузить все изображения из массива ссылок. Для каждой ссылки я создаю тему и делаю 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 () нарисует изображение. И когда приложение перейдет к следующей строке, я создам количество потоков, чтобы продолжить делать веб-запрос. И задержка случается, когда старый поток не завершен, но я создаю новые темы. Таким образом, любое предложение, почему у моего приложения была задержка? Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 08 января 2010

Создание нового потока на самом деле довольно медленное, и чем больше потоков вы используете одновременно в однопроцессорной системе, тем дольше каждый поток начинает работать после запуска. Что вам действительно нужно, так это ограничить число потоков чем-то разумным и запускать потоки только один раз, а затем просто повторно использовать их.

На самом деле Microsoft уже выполнила всю тяжелую работу по управлению пулом потоков для такого рода задач, которые называются пул потоков. Вы используете его следующим образом:

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));
}
2 голосов
/ 24 декабря 2009

Две возможные причины медлительности:

  1. В зависимости от значения ImgObjArr.Count, код в вопросе может создать большое количество потоков, все загружающие процессор. Сам код потока в основном безвреден - они ждут ответа HTTP, чтобы вернуться. Однако, если большое количество из них запускается одновременно, вы можете получить пики CPU, которые могут замедлить интерфейс. Это может произойти, когда запросы отправляются, и когда ответы начинают возвращаться, и код создает объекты Bitmap. Переключение контекста тоже имеет свою стоимость.

    Какое количество потоков слишком велико, зависит от мощности рассматриваемого процессора. Учитывая, что это вопрос компактной структуры, это будет нижняя часть спектра. Возможно, вы захотите ограничить количество фоновых потоков фиксированным размером пула. Некоторое число между 2-4 может быть правильным. Обратите внимание, что вы не получите много пользы от большего количества потоков, если инфраструктура в любом случае ограничит количество исходящих соединений. (должен быть установлен предел по умолчанию, установленный платформой, я полагаю, вы можете изменить 2 соединения. ОС может также установить предел)

  2. Код внутри ImageUpdate выполняется в потоке пользовательского интерфейса приложения. Любое потраченное время не доступно для обработки ввода. Это напрямую способствует задержкам пользовательского интерфейса. Если там есть какой-либо код, который можно было бы вставить в фоновый поток, это было бы полезным упражнением. Если весь код, который можно переместить в фоновый режим, уже был перемещен, уменьшение числа фоновых потоков все равно может помочь, поскольку это уменьшает вероятность одновременного попадания нескольких битовых карт в поток пользовательского интерфейса и создания связанных задержек.

...