WPF как работать с многопоточностью?
Есть следующий код:
private async void btnStart(object sender, RoutedEventArgs e)
{
int redirectCount = Convert.ToInt32(RedirectCount.Text);
int return_Count = 0; // Количество вызовов reg_link
reg_short_link reg_short_link = new reg_short_link();
for (int i = 0; i < redirectCount; i++)
{
string result = await Task.Factory.StartNew<string>(
() => reg_short_link.reg_link(redirectCount),
TaskCreationOptions.LongRunning);
this.result_link.Text = result + "\n";
}
}
reg_short_link.reg_link(redirectCount) выполняет определенные действия и возвращает строку которую мне нужно записать в result_link.Text.
В такой реализации все работает, что я хочу сделать:
Метод reg_link(redirectCount) нужно выполнить определенное количество (redirectCount) раз.
Нужно выполнить метод одновременно в большом количестве потоков (например в 50) при этом каждый раз при выполнении записать ответ в result_link.Text.
Как это сделать?
Ответы (1 шт):
Согласен с @EvgeniyZ, привязки Binding в WPF - это сама суть WPF. Рекомендую вам с ними ознакомиться. Можете зайти в мой профиль, там больше половины ответов про WPF, MVVM и привязки. На англоязычном SO тоже.
Вот вам решение по многопоточности, или если быть точнее, многозадачности
private async void btnStart(object sender, RoutedEventArgs e)
{
btnStart.IsEnabled = false; // кнопку лучше отключить, пока идет работа
int redirectCount = Convert.ToInt32(RedirectCount.Text);
int return_Count = 0; // Количество вызовов reg_link
reg_short_link reg_short_link = new reg_short_link();
int maxConcurrentTasks = Environment.ProcessorCount * 2; // можно 50, но обычно делают так
SemaphoreSlim semaphore = new SemaphoreSlim(maxConcurrentTasks);
IProgress<string> progress = new Progress<string>(s => result_link.Text += s + Environment.NewLine);
List<Task> tasks = new List<Task>();
for (int i = 0; i < redirectCount; i++)
{
await semaphore.WaitAsync(); // если больше чем maxConcurrentTasks, то ждем
tasks.Add(Task.Run(() =>
{
string result = reg_short_link.reg_link(redirectCount);
progress.Report(result);
semaphore.Release();
}));
}
await Task.WhenAll(tasks);
// все задачи завершены
btnStart.IsEnabled = true;
}
SemaphoreSlim- светофор, позволяет ограничить количество одновременно входящих в его зону задачIProgress- колбэк, выполняемый в контексте синхронизации того потока, в котором был созданProgress, то есть потокобезопасный вариант отправить что-то из параллельной задачи в интерфейс.
Будьте осторожны, если метод reg_link пишет куда-то данные, он должен быть потокобезопасным, иначе данные можно повредить, так как несколько параллельно выполняемых методов могу писать одновременно в одно и то же место. Если у вас там например Dictionary с этими строчками, то рассмотрите вариант с заменой на ConcurrentDictionary, либо используйте lock() для небезопасных фрагментов кода.
Или покажите этот метод (или вообще весь класс) в вопросе, я перепишу.