Pull to refresh

Comments 18

автор вам, конечно, спасибо
но это не статья это исходный код с комментариями :)

один вопрос, может быть для данной задачи имеет смысл сделать загрузку фидов по таймеру (скажем раз в минуту), а не в бесконечном цикле с паузой потока? я спросил исключительно из-за фразы «наоболее оптимален в таких задачах», интересно почему наимболее оптимален?
Я все-таки видимо не удачный пример взял… обычно такую схему я использую для «уведомления» Web-сервисов, о наступлении каких-то событий в БД (новые данные, который нужно обработать и т.п.). Можно использовать и таймер, здесь просто пример циклом, как наиболее распространенный подход (которые я встречал).

А по поводу исходного кода я отметил отдельно, что в коментариях рассказывается как используются определенные элементы.
Для «слежения» за бд есть штука — Sqldependency.
А еще есть Web-сервисы, с которых я получаю данные… Источник данных не важен, важно что данные там могут появится в любую минуту, и должны быть почти сразу обработаны. С другой стороны постоянные запросы к Web серверам, например, создадут ненужную нагрузку, но такие моменты можно всегда регулировать.
UFO landed and left these words here
Тут задача решается другими способами. Я для этого обычно использую асинхронный вызов делегата, если нужно выполнить свой метод, либо использую методы для асинхронных вызовов в классе, которые их предоставляет.
А теперь с использованием Parallel Extensions CTP:
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading;

namespace ParallelRSS
{
  class Program
  {
    private static string ProcessRSS(string feedUrl)
    {
      HttpWebRequest request = (HttpWebRequest)WebRequest.Create(feedUrl);
      var response = request.GetResponse();
      return (new StreamReader(response.GetResponseStream())).ReadToEnd();
    }

    private static string[] GetURLs()
    {
      return new string[] {
        "habrahabr.ru/rss/",
        "www.cbr.ru/scripts/RssPress.asp"
      };
    }

    static void Main(string[] args)
    {
      try
      {
        var data = GetURLs().AsParallel().Select(url => ProcessRSS(url));
        foreach (string x in data)
        {
          Console.WriteLine(x);
        }
      }
      catch (AggregateException e)
      {
        
      }
      Console.Read();
    }
  }
}

* This source code was highlighted with Source Code Highlighter.

Я не профессиональный .NET-разработчик, и код вполне может содержать фатальные недостатки по сравнению с примером в статье. Но концепция мне очень нравится :-)
LINQ для процессов? 8-))) Хахаха, это похоже на MSStyle 8-). Прикольная концепция. Но не очень проста для понимания.
Симпатично… по моему все понятно.
Для подобных задач намного лучше подходить ThreadPool. Когда потоки простые и однотипные, вы просто создаёте ThreadPool и размещаете в нём задания. Он сам парралелит на оптимальное или указанное число потоков ваши задания, и вам не надо следить за количеством тредов. + ресайклинг.

Подробно в MSDN

Вот собственно говоря, оттуда самый простой пример работы.

class MainApp
{
  static void Main()
  {
   for(int i=0;i<30;i++)
   {
     ThreadPool.QueueUserWorkItem(new WaitCallback(PoolFunc));
   }
   Console.ReadLine();
  }

  static void PoolFunc(object state)
  {
   int workerThreads,completionPortThreads;
   ThreadPool.GetAvailableThreads(out workerThreads,
     out completionPortThreads);
   Console.WriteLine("WorkerThreads: {0}, CompletionPortThreads: {1}",
     workerThreads, completionPortThreads);

   Thread.Sleep(15000);
   ConnectionSocket connection = new ConnectionSocket();
   connection.Connect();
  }
}


* This source code was highlighted with Source Code Highlighter.

Так вы видимо не заметили, что для обработки каждого элемента данных и используется ThreadPool. Отдельный поток только для того, что бы не блокировался основной поток приложения.
Ну, вот как-то странно выходит. Главный поток не поточить через него?
Блин, из за вас теперь сижу в студии, и думаю, как оптимизировать 8-)))
С технической точки зрения — всё правильно. Спорно конечно про бесконечный цикл, но на это можно сейчас забить. Есть объекты синхронизации, правильные инкременты. Но, вот просто мне думается, что это можно как-то упростить.
Использование ThreadPool не приведёт к блокировке основного потока.
Думаю, лучше использовать System.Threading.Timer в качестве альтернативы вашему основному потоку. Всё же выглядит лучше, чем while (true).
ThreadPool не блокирует, а вот постоянная выборка данных блокирует, именно она вынесена в отдельный поток.

Можно использовать Timer, но тогда нельзя будет использовать собственные алгоритмы задержки… А менять постоянно число таймера… какой смысл тогда в нем? У меня например есть задача проверки обработанных данных на удаленном Web сервисе, сначало через 1 минуту, затем через 5 минут, потом через 10 минут, потом снова через 1 минуту, потом еще через 30 секунд… Думаете с таймером будет удобнее?
Всё зависит от задачи. В приведённом коде таймер оптимальней.
Кстати для синхронизации доступа к List стоит использовать SyncRoot:
lock (ResultData.SyncRoot)
{
ResultData.Add(response);
}
Sign up to leave a comment.

Articles