Я не видел ни одного сообщения, имеющего отношение к моей проблеме, поэтому я прошу прощения, если я отправляю уже заданный вопрос.
У меня есть программа windows form, c #, которая проверяет запасы и делает анализ. Основная форма запускает другую форму через новый поток и ShowDialog. Пока он загружается, он работает параллельно. В этом параллельном примере я хотел бы показать прогресс в основной форме.
Я столкнулся с проблемами многопоточности и добавил invoke, хотя он не кажется поточно-ориентированным, поскольку кажется, что он заходит в тупик к концу параллельного .foreach. Я пробовал делегатов, события, не повезло. Помоги мне, Оби-Ван, ты моя единственная надежда!
Урезанная версия:
Основная форма
private void button1_Click(object sender, EventArgs e)
{
YearLows yearLows = new YearLows();
Thread yearLowsThread = new Thread(() => StartYearLows(yearLows));
yearLowsThread.Start();
btnGetYearLows.Enabled = false;
}
private void StartYearLows(YearLows yearLows)
{
yearLows.ShowDialog();
}
public void UpdateProgress(string text)
{
lblProgress.Text = text;
}
2-й диалог формы
public partial class YearLows : Form
{
private void YearLows_Load(object sender, EventArgs e)
{
// work
Parallel.ForEach(responseStocks, new ParallelOptions { MaxDegreeOfParallelism = MaxThreads }, x =>
{
// more work
Interlocked.Increment(stocksProcessed);
UpdateProgress($"{stocksProcessed} / {stocksTotal} Researched");
});
}
private void UpdateProgress(string text)
{
Invoke(new Action(() => frmMain.UpdateProgress(text)));
}
}
Обновление 1:
Если я переместу метку обновления прогресса в дочернюю форму, то, похоже, я получаю все обновления прогресса. Мне пришлось перейти от события Load к событию Shown, чтобы форма отображалась, чтобы пользователи могли видеть обновления прогресса. Я должен был следовать совету SLaks и запустить Task.Run (() => Parallel.ForEach. Это будет работать для меня. Тем не менее, я хотел бы выяснить, почему он все еще блокируется к концу, если я хотел обновления прогресса на главной форма (я всегда читал, что async void был плохим, но я не думаю, что это можно обойти в этих сигнатурах определенных методов в winforms)
public partial class YearLows : Form
{
private async void YearLows_Shown(object sender, EventArgs e)
{
await AnalyzeStocks();
}
private async Task AnalyzeStocks(object sender, EventArgs e)
{
// work
await Task.Run(() => Parallel.ForEach(responseStocks, new ParallelOptions { MaxDegreeOfParallelism = MaxThreads }, x =>
{
// more work
Interlocked.Increment(stocksProcessed);
UpdateProgress($"{stocksProcessed} / {stocksTotal} Researched");
}));
}
private void UpdateProgress(string text)
{
Invoke(new Action(() => lblProgress.UpdateProgress(text)));
}
}