2013-08-29 3 views
0

видя это решение, указанное в Divide Foreach into threads sampleвыполняющиеся задачи паралельно в asp.net

Я пытался реализовать его с помощью этого кода:

foreach (Object vo in arrreclist) 
{ 
    msg = String.Empty; 
    objprocess.GetType().GetMethod("ProcessRecord").Invoke(objprocess, new Object[] { vo }); 

    status = (StatusInfo)objprocess.GetType().GetProperty("status").GetValue(objprocess, null); 
    if (status.errcode != 0) 
    { 
     lngfailedcnt++; 
     WriteErrorLog(); 
    } 
    else 
    { 
     lngsuccesscnt++; 
     lngInstanceSuccCount++; 
    } 
    lngcnt++; 
    if ((lngcnt % 10) == 0) 
    { 

     if (instanceId == 0) 
     { 
      schldr.ModifyJobhistoryForUploadFileRecCnt(Runid, (int)lngTotreccnt, lngfailedcnt, (int)(lngfailedcnt + lngsuccesscnt)); 
     } 
     else 
     { 
      schldr.ModifyJobhistoryForUploadFileRecCnt(Runid, 0, lngfailedcnt, (int)(lngfailedcnt + lngsuccesscnt)); 
     } 
     status = schldr.status; 
     if (status.errcode != 0) 
     { 
      if (!String.IsNullOrEmpty(Errorlogfile)) 
       WriteErrorLog(); 
      holdInstance = true; 
      break; 
     } 
     //Get Job Status 
     //If job was terminated then Update Batch and Job history with status as STOPPED 
     intstatus = schedulersvc.GetJobStatus(Runid); 
     status = schedulersvc.status; 
     if (status.errcode != 0) 
     { 
      WriteErrorLog(); 
      holdInstance = true; 
      break; 
     } 
     if (intstatus == 1) //STOPPED 
     { 
      holdInstance = true; 
      break; 
     } 
     lngcnt = 0; 
    } 
} 

И сообщение об ошибке наступающем для постановки излома:

не может покинуть тело анонимного метода или выражения лямбда

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

objprocess.GetType().GetMethod("ProcessRecord").Invoke(objprocess, new Object[] { vo }) 

Но другие иждивенцы, так как реализовать?

+0

Прежде всего, почему вы используете Reflection? Вместо этого, почему бы вам не определить интерфейс & Use Parallel.ForEach –

+0

Ваша ошибка не совпадает с кодом, который вы отправили: я не вижу там никаких лямбдов. – svick

+0

Кроме того, когда вы говорите, что хотите распараллелить только эту строку, означает ли это, что остальная часть цикла не может работать параллельно? – svick

ответ

1

Во-первых, распараллеливание часто не имеет смысла в ASP.NET. Если у вас есть много пользователей, которые обращаются к вашему сайту, вы, как правило, больше заботитесь о масштабируемости (сколько пользователей вы можете одновременно обслуживать), чем сырая производительность для одного пользователя.

Если это не ваш случай, распараллеливание может иметь смысл для вас.

Во-вторых, вы получаете эту ошибку, потому что Parallel.ForEach() не является циклом (насколько это касается языка). И break Выйти из лямбды не имеет никакого смысла.

Чтобы вырваться из Parallel.ForEach(), вы можете использовать ParallelLoopState.Break() или ParallelLoopState.Stop() (прочтите документацию, чтобы узнать, какой из них вы действительно хотите). Для этого вам необходимо использовать перегрузку Parallel.ForEach(), которая дает вам ParallelLoopState.

В-третьих, есть веская причина, почему Parallel.ForEach() не поддерживает ArrayList: это потому, что вы никогда не должны его использовать. Если вам действительно нужен список object, используйте List<object>, чтобы было ясно, что вы действительно не знаете тип. Если вы не можете (или не хотите) изменить ArrayList, вы можете использовать .Cast<object>(), чтобы сделать Parallel.ForEach() (и другие методы, которые работают с IEnumerable<T>) принимают его.

В-четвертых, я считаю, что распараллеливание только ProcessRecord не имеет смысла. Похоже, status возвращает статус для последнего ProcessRecord. И если вы выполните ProcessRecord параллельно, то уже не ясно, какой из них является последним.

Кроме того, вы не должны думать, что некоторые методы не являются потокобезопасными. Ты должен знать что. Если вы распараллеливаете то, что вы не знаете, это потокобезопасно, вам, вероятно, придется тяжело отлаживать ошибки позже.

В-пятых, если вы хотите распараллелить только первую часть цикла, я думаю, что лучшим вариантом является PLINQ. Что-то вроде:

var intermediateResults = source.AsParallel().Select(x => Process(x)); 

foreach (var intermediateResult in intermediateResults) 
{ 
    // the rest of the loop 
} 
Смежные вопросы