Czy są jakieś zmiany, które wielu pracowników tła wykonuje lepiej niż zadania w 5-sekundowych uruchomionych procesach? Pamiętam, jak czytałem w książce, że zadanie jest przeznaczone dla krótkich procesów.zadanie pracownik tła C#
reasong pytam to:
Mam procesu, który trwa 5 sekund, aby zakończyć, i istnieje 4000 zakończenie procesów. Na początku robiłam:
for (int i=0; i<4000; i++) {
Task.Factory.StartNewTask(action);
}
i ten miał słabe wyniki (po pierwszej minucie, gdzie 3-4 zadania zakończone, a aplikacja konsoli miał 35 wątków). Może to było głupie, ale pomyślałem, że pula wątków poradzi sobie z taką sytuacją (wszystkie akcje zostaną umieszczone w kolejce, a gdy wątek jest wolny, wykona akcję i wykona ją).
Drugim krokiem było ręczne wykonanie zadań dla środowiska Environment.ProcessorCount i wszystkich akcji, które należy umieścić w ConcurentQueue. Kod będzie wyglądał mniej więcej tak:
var workers = new List<BackgroundWorker>();
//initialize workers
workers.ForEach((bk) =>
{
bk.DoWork += (s, e) =>
{
while (toDoActions.Count > 0)
{
Action a;
if (toDoActions.TryDequeue(out a))
{
a();
}
}
}
bk.RunWorkerAsync();
});
To było lepsze. Wykonał znacznie lepiej niż zadania, nawet gdy miałem 30 pracowników w tle (tyle zadań, co w pierwszym przypadku).
LE:
zacznę Zadania tak:
public static Task IndexFile(string file)
{
Action<object> indexAction = new Action<object>((f) =>
{
Index((string)f);
});
return Task.Factory.StartNew(indexAction, file);
}
A metoda Index jest to jedno:
private static void Index(string file)
{
AudioDetectionServiceReference.AudioDetectionServiceClient client = new AudioDetectionServiceReference.AudioDetectionServiceClient();
client.IndexCompleted += (s, e) =>
{
if (e.Error != null)
{
if (FileError != null)
{
FileError(client,
new FileIndexErrorEventArgs((string)e.UserState, e.Error));
}
}
else
{
if (FileIndexed != null)
{
FileIndexed(client, new FileIndexedEventArgs((string)e.UserState));
}
}
};
using (IAudio proxy = new BassProxy())
{
List<int> max = new List<int>();
if (proxy.ReadFFTData(file, out max))
{
while (max.Count > 0 && max.First() == 0)
{
max.RemoveAt(0);
}
while (max.Count > 0 && max.Last() == 0)
{
max.RemoveAt(max.Count - 1);
}
client.IndexAsync(max.ToArray(), file, file);
}
else
{
throw new CouldNotIndexException(file, "The audio proxy did not return any data for this file.");
}
}
}
Metoda ta odczytuje z pliku mp3 niektóre dane, używając biblioteka Bass.net. Następnie dane są wysyłane do usługi WCF, przy użyciu metody asynchronicznej. Metoda IndexFile (ciąg plików), która tworzy zadania, jest wywoływana 4000 razy w pętli for. Te dwa zdarzenia, FileIndexed i FileError nie są obsługiwane, więc nie są nigdy zgłaszane.
Możesz użyć 'BlockingCollection' zamiast' ConcurrentQueue' (użyje on 'ConcurrentQueue' wewnętrznie). Sprawi, że kod będzie nieco czystszy i łatwiejszy w użyciu. – Servy
Dzięki za podpowiedź ... Zmienię :) –
Czy próbowałeś 'Parallel.Invoke' z szeregiem działań? – mellamokb