2015-03-24 2 views
0

Привет, ребята, я пытался сделать асинхронный подход к моей функции, связанной с процессором, которые вычисляют некоторые совокупные функции. Дело в том, что есть какой-то тупик (я полагаю), потому что время вычисления слишком отличается. Я reallz новичок в этой задаче Параллельный мир, я также читаю статьи Stephem Cleary, но я все еще не уверен во всем аспекте этого асинхронного подхода. Мой код:Асинхронные задачи занимают слишком много времени

private static void Main(string[] args) 
{ 
    PIServer server = ConnectToDefaultPIServer(); 
    AFTimeRange timeRange = new AFTimeRange("1/1/2012", "6/30/2012"); 
    Program p = new Program(); 
    for (int i = 0; i < 10; i++) 
    { 
     p.TestAsynchronousCall(server, timeRange); 
     //p.TestAsynchronousCall(server, timeRange).Wait();-same results 
    } 
    Console.WriteLine("Main check-disconnected done"); 
    Console.ReadKey(); 
} 

private async Task TestAsynchronousCall(PIServer server, AFTimeRange timeRange) 
{ 
    AsyncClass asyn; 
    for (int i = 0; i < 1; i++) 
    { 
     asyn = new AsyncClass(); 
     await asyn.DoAsyncTask(server, timeRange); 
     //asyn.DoAsyncTask(server, timeRange);-same results 
    } 
} 

public async Task DoAsyncTask(PIServer server, AFTimeRange timeRange) 
{ 
     var timeRanges = DivideTheTimeRange(timeRange); 
     Task<Dictionary<PIPoint, AFValues>>[] tasksArray = new Task<Dictionary<PIPoint, AFValues>>[2]; 

     tasksArray[0] = (Task.Run(() => CalculationClass.AverageValueOfTagPerDay(server, timeRanges[0]))); 
     // tasksArray[1] = tasksArray[0].ContinueWith((x) => CalculationClass.AverageValueOfTagPerDay(server, timeRanges[1])); 
     tasksArray[1] = (Task.Run(() => CalculationClass.AverageValueOfTagPerDay(server, timeRanges[1]))); 


     Task.WaitAll(tasksArray); 
     //await Task.WhenAll(tasksArray); -same results 
     for (int i = 0; i < tasksArray.Length; i++) 
     { 
      Program.Show(tasksArray[i].Result); 
     } 
} 

измеряю время Повсеместно Секундомер в функциях AverageValueOfTagPerDay. Эта функция синхронна (это проблема?). Каждая задача занимает 12 секунд. Но когда я раскомментировал строку и использовал метод ContinueWith(), эти Задачи занимают 5-6 секунд каждый (что желательно). Как это возможно? Более странно то, что когда я устанавливаю цикл for в Main() на 10, иногда это занимает 5 секунд, а также когда я использую ContinueWith(). Поэтому я предполагаю, что где-то тупик, но я не могу это найти. Извините за английский, у меня все еще проблема, создающая хорошие обратные отсчеты, когда я пытаюсь объяснить некоторые трудности. Приветствие UPDATE я удалил попробовать, который является устаревшим для большей ясности

+1

вы понимаете, что ваш сначала для следующего будет выполнение каждой итерации последовательно. Почему бы не использовать forparallel? –

+0

DoAsyncTask является неполным: 'try' без' catch' и 'finally'. Он помечен как 'async', но не использует' await'. У вас есть несколько задач с использованием одного и того же экземпляра 'PIServer', является ли этот класс потоком безопасным? – Guillaume

+0

поэтому он даже не компилируется. AsyncTask не должен быть асинхронным. –

ответ

3

Привет ребят Я пытаюсь сделать асинхронный подход к моему CPU переплета функции, вычислить некоторые агрегатные функции.

«Асинхронные» и «связанные с процессором» не являются терминами, которые объединяются. Если у вас есть процесс с привязкой к процессору, вы должны использовать параллельные технологии (Parallel, параллельный LINQ, поток данных TPL).

Я новичок в этой задаче Параллельный мир, я также читаю статьи Stephem Cleary, но я все еще не уверен во всем аспекте этого асинхронного подхода.

Возможно, потому что я не рассматриваю параллельные технологии в любых моих статьях или сообщениях в блоге. :) Я их покрываю в своей книге, но не в Интернете. В моей онлайн-работе основное внимание уделяется асинхронности, которая идеально подходит для операций на основе ввода-вывода.

Чтобы решить проблему, вы должны использовать параллельный подход:

public Dictionary<PIPoint, AFValues>[] DoTask(PIServer server, AFTimeRange timeRange) 
{ 
    var timeRanges = DivideTheTimeRange(timeRange); 
    var result = timeRanges.AsParallel().AsOrdered(). 
     Select(range => CalculationClass.AverageValueOfTagPerDay(server, range)). 
     ToArray(); 
    return result; 
} 

Конечно, этот подход предполагает, что PIServer является поточно. Он также предполагает, что класс ввода-вывода не выполняется в/в; если есть, то поток данных TPL может быть лучшим выбором, чем Parallel LINQ.

Если вы планируете использовать этот код в приложении интерфейса и не хотите, чтобы блокировать поток пользовательского интерфейса, то вы можете вызов код асинхронно, как это:

var results = await Task.Run(() => DoTask(server, timeRange)); 
foreach (var result in results) 
    Program.Show(result); 
+0

Спасибо Стивен, я всегда, хотя этот асинхронный подход не подходит для операций, связанных с процессором, но когда я прочитал вас [статья] (http://blog.stephencleary.com/2013/10/taskrun-etiquette-and-proper- usage.html) Вы писали: _So, остается вопрос: где я должен использовать Task.Run?Use Task.Run для вызова методов с привязкой к CPU. Это все. Я тоже читал твою книгу, потому что я очень увлекаюсь этим. И я имел в виду ссылку на параллельную библиотеку задач, которая использует Task. Поэтому я все еще немного запутался в правильных именах. Я считаю, что PiServer является потокобезопасным, я попробую его, и я дам вам знать –

+0

Ну, я попробовал этот AsParallel(), и я получил тот же результат (по 12 секунд для каждого), и моя цель в том, что этот расчет составляет менее 6 секунд , Поэтому я посмотрю на TPL Dataflow. Также я должен был упомянуть, что это чисто консольное приложение, и что функция агрегации, которая вычисляет среднее значение для каждого дня, выдает на стороне сервера (что в данном случае является моим локальным сервером). Поэтому я полагаю, что он удовлетворяет требованиям ввода-вывода. Я имею в виду, что вывод с сервера - это конкретные средние значения. BTW Большое спасибо за ответ :-) –

+0

@Alexander_Dracka: Если я правильно вас понимаю, то операция * для этого процесса * связана с I/O-привязкой, а не с ЦП. И в этом случае вы, вероятно, захотите использовать 'async' с' Task.WhenAll'. Одна вещь, чтобы проверить (если ваш сервер является ASP.NET) заключается в том, что запрос на сервер отключен. –

Смежные вопросы