Có bất kỳ thay đổi nào mà nhiều Nhân viên nền thực hiện tốt hơn Task trên 5 quy trình đang chạy thứ hai không? Tôi nhớ đọc trong một cuốn sách mà một nhiệm vụ được thiết kế cho các quy trình chạy ngắn.Nhân viên nền công việc C#
Yêu cầu tôi hỏi là:
Tôi có quá trình mất 5 giây để hoàn thành và có 4000 quy trình để hoàn tất. Lúc đầu, tôi đã làm:
for (int i=0; i<4000; i++) {
Task.Factory.StartNewTask(action);
}
và điều này có hiệu suất kém (sau phút đầu tiên, 3-4 công việc hoàn thành và ứng dụng bàn điều khiển có 35 chủ đề). Có lẽ điều này là ngu ngốc, nhưng tôi nghĩ rằng hồ bơi thread sẽ xử lý loại tình huống này (nó sẽ đặt tất cả các hành động trong một hàng đợi, và khi một thread là miễn phí, nó sẽ có một hành động và thực hiện nó).
Bước thứ hai bây giờ là thực hiện thủ công Environment.ProcessorCác nhân viên nền tảng toàn cầu và tất cả các hành động được đặt trong ConcurentQueue. Vì vậy, mã sẽ trông giống như sau:
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();
});
Cách này hoạt động tốt hơn. Nó thực hiện tốt hơn nhiều sau đó các nhiệm vụ ngay cả khi tôi đã có 30 công nhân nền (như nhiều nhiệm vụ như trong trường hợp đầu tiên).
LE:
tôi bắt đầu nhiệm vụ như thế này:
public static Task IndexFile(string file)
{
Action<object> indexAction = new Action<object>((f) =>
{
Index((string)f);
});
return Task.Factory.StartNew(indexAction, file);
}
Và phương pháp Index là này một:
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.");
}
}
}
phương pháp này đọc từ một mp3 nộp một số dữ liệu, sử dụng thư viện Bass.net. Sau đó, dữ liệu đó được gửi đến một dịch vụ WCF, sử dụng phương thức async. Phương thức IndexFile (chuỗi tệp), tạo nhiệm vụ được gọi cho 4000 lần trong vòng lặp for. Hai sự kiện đó, FileIndexed và FileError không được xử lý, vì vậy chúng không bao giờ bị ném.
Bạn có thể muốn sử dụng 'BlockingCollection' thay vì' ConcurrentQueue' (nó sẽ sử dụng 'ConcurrentQueue' nội bộ). Nó sẽ làm cho mã một chút sạch hơn và dễ sử dụng hơn. – Servy
Cảm ơn lời khuyên ... Tôi sẽ thay đổi :) –
Bạn đã thử 'Parallel.Invoke' với một loạt các hành động chưa? – mellamokb