Моя основная программа работает с 8 задачами, используя Task.Factory.StartNewКак анализировать XML из HttpWebRequest асинхронно?
Каждая задача запрашивает результат XML-формата из webservice, а затем разбирается в коллекции, которая может быть записана в MSSQL с использованием TVP.
Программа работает, но коэффициент полезного действия с использованием TPL - это не то, что я ожидал. После использования секундомера в разных точках мне кажется, что задачи мешают друг другу, возможно, одна блокирует другую. Все цифры указывают на раздел загрузки, в котором используется HttpWebRequest.
После поиска и чтения бит в асинхронном программировании в C# я попытался изменить свой код, чтобы запустить секцию загрузки асинхронно, но результат по-прежнему демонстрирует аналогичный уровень блокировки без использования асинхронного кодирования.
Есть три типа кодирования, я нашел и несколько ссылок ссылки на них:
How to use HttpWebRequest (.NET) asynchronously? -Когда я использую этот метод, я прохожу в XDocument вокруг с помощью пользовательского объекта в методе загрузки раздела
Асинхронное программирование в C# используя итераторы http://tomasp.net/blog/csharp-async.aspx -string/поток возвращается и анализировать с помощью XDocument.Load/разбор в основном методом
Ниже блока кода показывает последний метод найден и реализован в моем коде
Главный класс, начать задачи
private static void test() {
DBReader dbReader = new DBReader();
Dictionary<string, DateTime> jobs = dbReader.getJob();
JobHandler jh = new JobHandler();
Stopwatch swCharge = new Stopwatch();
Stopwatch swDetail = new Stopwatch();
Stopwatch swHeader = new Stopwatch();
//more stopwatch
Task[] tasks = new Task[] {
Task.Factory.StartNew(() => jh.processData<RawChargeCollection, RawCharge>(jobs["RawCharge"], 15, swCharge)),
Task.Factory.StartNew(() => jh.processData<RawDetailCollection, RawDetail>(jobs["RawDetail"], 15, swDetail)),
Task.Factory.StartNew(() => jh.processData<RawHeaderCollection, RawHeader>(jobs["RawHeader"], 15, swHeader))
};
Task.WaitAll(tasks);
}
Метод ProcessData
public void processData<T, S>(DateTime x, int mins, Stopwatch sw)
where T : List<S>, new()
where S : new() {
DateTime start = x;
DateTime end = x.AddMinutes(mins);
string fromDate, toDate;
StringBuilder str = new StringBuilder();
XMLParser xmlParser = new XMLParser();
DBWriter dbWriter = new DBWriter();
while (end <= DateTime.UtcNow) {
fromDate = String.Format("{0:yyyy'-'MM'-'dd HH':'mm':'ss}", start);
toDate = String.Format("{0:yyyy'-'MM'-'dd HH':'mm':'ss}", end);
try {
sw.Restart();
WebserviceClient ws = new WebserviceClient();
XDocument xDoc = null;
var task = ws.GetRawData<S>(fromDate, toDate);
xDoc = XDocument.Parse(task.Result);
//show the download time
sw.Restart();
T rawData = xmlParser.ParseXML<T, S>(xDoc);
if (rawData.Count != 0) {
sw.Restart();
dbWriter.writeRawData<T, S>(rawData, start, end);
//log success
}
else {
//log no data
}
}
catch (Exception e) {
//log fail
}
finally {
start = start.AddMinutes(mins);
end = end.AddMinutes(mins);
}
}
}
GetRawData просто ответственность для построения нужен URL, используемый в GetData.
Скачать раздел данных:
private static Task<string> GetData(string param) {
string url = String.Format("my working URL/{0}", param);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.MediaType = "application/xml";
Task<WebResponse> task = Task.Factory.FromAsync(
request.BeginGetResponse,
asyncResult => request.EndGetResponse(asyncResult),
(object)null);
return task.ContinueWith(t => ReadStreamFromResponse(t.Result));
}
private static string ReadStreamFromResponse(WebResponse response) {
using (Stream responseStream = response.GetResponseStream())
using (StreamReader sr = new StreamReader(responseStream)) {
//Need to return this response
string strContent = sr.ReadToEnd();
return strContent;
}
}
В методе ProcessData я приурочил код, необходимый для загрузки с веб-сервиса. Скачивание занимает от 400 мс до 100000 мс. Нормальное время от 3000 до 8000 мс. Если я просто запустил 1 задачу, время клиентского процесса немного больше времени сервера.
Однако после запуска большего количества задач загрузка, которая занимает от 450 мс до 3000 мс (или что-то еще) на сервере, теперь может занять до 8000мс -90000мс для завершения клиентом процесса загрузки.
В моем сценарии узкое место должно быть на стороне сервера, из моего журнала это показывает, что клиент есть.
Основная статья, найденная для асинхронного программирования C#, кажется, демонстрирует чтение и обработку потока/строки без примера для XML. Является ли мой код неудачным из-за XML ?? Если нет, то в чем проблема моего кода?
EDIT: Да моя DEV машина и пользователи/целевая машина XP, слишком много, чтобы использовать .net 4.5 или CTP.
ServicePointManager.DefaultConnectionLimit и app.config connectionManagement похоже на одно и то же, поэтому я выбираю app.config, так как это можно изменить.
Вначале очень важно сменить максимальное подключение, но на самом деле не решило проблему. После кода временного кода с помощью Thread.Sleep (random) кажется, что «блокировка» не относится к параллельному коду.
Процесс сначала загружается из webservice (здесь требуется максимальное соединение), затем выполняйте некоторые незначительные сопоставления, наконец, записывайте в БД, запись в БД никогда не занимает более 1 секунды, по сравнению с загрузкой ничего не было, но после добавления максимального соединения к DB (тот же номер, что и webservice), не было никакого ожидания внезапно.
Таким образом, максимальное соединение с БД также имеет значение. Но я не понимаю, почему запись в DB с 150-600ms может вызвать ожидание более 20 секунд.
Что меня даже смущает, время ожидания находилось в блоке загрузки, а не в блоке записи БД.
, учитывая тег 4.0, я предполагаю, что это не вариант для вас, но если/когда вы можете начать использовать 4.5, новый класс HttpClient является «изначально» асинхронным и делает асинхронную обработку ответов намного проще ИМХО - http://msdn.microsoft.com/en-us/library/system.net.http.httpclient(VS.110).aspx –