2009-12-24 3 views
1

В моем мобильном приложении я хочу загрузить все изображения из архаиста ссылок. Для каждой ссылки я создаю поток и делаю httpwebrequest. Проблема в том, что мое приложение работает негладко. Кажется, что вы получаете задержку каждый раз, когда я создаю новый поток, и когда поток выполняется (когда выполняется поток, я нарисую img на фон). Вот мой код:C# compact framework: многопоточная причина задержки?

  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

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

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

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

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

+0

Во-первых, большое спасибо за ваш ответ. Итак, как вы полагаете, я должен ограничивать потоки, доступные за один раз. Но как насчет того, если один веб-запрос http встретил исключение тайм-аута запроса. По умолчанию мое приложение сначала имеет 9 изображений (и 9 потоков). Затем каждую навигацию загружают более 3 потоков (по 3 img каждой строки). Есть ли совет для меня? Thanks – Thyphuong

+0

Несколько мыслей; если группы изображений всегда загружаются вместе - например, 9, 3 или всего 36 - может быть более эффективным загрузить большое изображение, содержащее изображения, которые вам нужны в качестве плиток. Это уменьшит количество запросов/ответов. Что касается тайм-аутов, пул из 4 потоков должен иметь возможность обрабатывать случайные запросы без значительного влияния на пользователя.Если служба отключена или связь потеряна, любое количество потоков будет просто висеть там. –

+0

Это не группа. Изображения представляют собой отдельные изображения из разных ссылок. – Thyphuong

2

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

На самом деле 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)); 
} 
Смежные вопросы