Страницы

Поиск по вопросам

пятница, 9 ноября 2018 г.

C# Почему async/await может тормозить

C# async/await
public partial class MainWindow : Window { private static object sync = new object();
public MainWindow() { InitializeComponent(); }
private void btnStart_Click(object sender, RoutedEventArgs e) { Random rnd = new Random();
for (int i = 0; i <= 100; ++i) { KeyValuePair pr = new KeyValuePair(i.ToString(), rnd.Next(1251000, 1259999).ToString()); ProcessingTransactionAsync(pr); } }
private async void ProcessingTransactionAsync(KeyValuePair trn) { this.WriteLog($"{trn.Key}_{trn.Value}", $"----> 1");
TestResult trnRes = await Task.Run((Func)(() => { this.WriteLog($"{trn.Key}_{trn.Value}", $"----> 2"); return this.ProcessingTransaction(trn); })); }
private TestResult ProcessingTransaction(KeyValuePair trn) { this.WriteLog($"{trn.Key}_{trn.Value}", $"----> 3");
//Здесь ещё функции, функции, функции Thread.Sleep(1000);
TestResult value = new TestResult(); this.WriteLog($"{trn.Key}_{trn.Value}", $"----> 4"); return value; }
#region Additional
private void WriteLog(string nameLogFile, string message) { try { string pathToLog = "Log";
if (!Directory.Exists(pathToLog)) Directory.CreateDirectory(pathToLog);
string filename = Path.Combine(pathToLog, string.Format("{0}.log", nameLogFile)); string fullText = string.Format("[{0:dd.MM.yyy HH:mm:ss.fff}] {1}
", DateTime.Now, message); lock (sync) File.AppendAllText(filename, fullText, Encoding.GetEncoding("Windows-1251")); } catch { // Перехватываем все и ничего не делаем } }
#endregion }
На первой итерации в лог пишется сл.:
[21.06.2017 16:53:49.998] ----> 1 [21.06.2017 16:53:50.022] ----> 2
При 100 итерации
[21.06.2017 16:56:44.937] ----> 1 [21.06.2017 16:56:52.672] ----> 2
Что программа может делать так долго(около 8 секунд) между шагами "----> 1" и "----> 2" на 100 итерации? Можно ли это как-то исправить?


Ответ

Вы запускаете в цикле одновременно 100 тасков (ProcessingTransactionAsync): вы не дожидаетесь их окончания. Каждый из них запускает внутренний таск через Task.Run на пуле потоков.
Пул потоков работает так: если есть свободный поток, то задание выполняется на нём. Если нет, система пытается создать новые потоки до MaxThreads. Если потоков и так слишком много, система думает, что вы просто создаёте задания, не дожидаясь результата, и не создаёт новых потоков, а просто ждёт, пока какой-то из рабочих потоков не освободится, и лишь тогда отдаёт ему задание.
Думаю, у вас случилось именно это.

Комментариев нет:

Отправить комментарий