• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

Многопоточность, Progressbar!

  • Автор темы KIA1990
  • Дата начала
K

KIA1990

Доброго времени суток!
Проблема такая:
У меня есть класс(dll), работает очень очень долго
и есть форма на которой желательно бы отследить работу класса(метода).
Не могу понять как это сделать!

В отдельный поток нужно передавать void методы без параметров??
Или как то можно с параметрами, просто необходимо передать методу FileStram.


Вот. :huh:
 
L

LuMee

Наиболее простой вариант отслеживания: сделать в твоем классе событие, аргумент которого содержал бы текущий прогресс. Далее, по мере выполнения "долгоиграющего" метода время от времени дергать это событие. Обработчик события будет обновлять прогресс бар.
Класс будет выглядеть примерно так:
Код:
public class ProgressChangedEventArgs : EventArgs
{
public int CurrentProgress { get; set; }
}

public delegate void ProgressChangedHandler(object sender, ProgressChangedEventArgs e);

public class WorkingClass
{
public event ProgressChangedHandler ProgressChanged;

private void OnProgressChanged(int progress)
{
ProgressChangedHandler handler = this.ProgressChanged;
if (handler != null)
handler(this, new ProgressChangedEventArgs { CurrentProgress = progress });
}

private void DoLotsOfWork(object data)
{
// Достаем FileStream
FileStream stream = data as FileStream;
if (stream == null)
throw ArgumentException("Надо было все-таки передать нормальный FileStream", "data");

OnProgressChanged(0);

// Делаем один кусок работы, скажем, четверть, после чего сообщаем об этом "наверх"
...
OnProgressChanged(25);

// Делаем еще один кусок, скажем, уже 2/3 работы сделано
...
OnProgressChanged(66);

//Ну и вроде как все доделали
...
OnProgressChanged(100);
}

public Thread DoLotsOfWorkAsync(FileStream stream)
{
Thread thread = new Thread(new ParameterizedThreadStart(this.DoLotsOfWork));
thread.Start(stream);

return thread;
}
}
Соответственно, использоваться это добро будет примерно так:
Код:
WorkingClass wc = new WorkingClass();
wc.ProgressChanged += delegate (object sender, ProgressChangedEventArgs e)
{
if (progressBar.InvokeRequired)
progressBar.Invoke(delegate (int progress) { progressBar.Value = progress; },
new Object[] { e.CurrentProgress });
else
progressBar.Value = e.CurrentProgress;
};

FileStream stream = ...;
ws.DoLotsOfWorkAsync(stream);
 
K

KIA1990

Наиболее простой вариант отслеживания: сделать в твоем классе событие, аргумент которого содержал бы текущий прогресс. Далее, по мере выполнения "долгоиграющего" метода время от времени дергать это событие. Обработчик события будет обновлять прогресс бар.
Класс будет выглядеть примерно так:
Код:
public class ProgressChangedEventArgs : EventArgs
{
public int CurrentProgress { get; set; }
}

public delegate void ProgressChangedHandler(object sender, ProgressChangedEventArgs e);

public class WorkingClass
{
public event ProgressChangedHandler ProgressChanged;

private void OnProgressChanged(int progress)
{
ProgressChangedHandler handler = this.ProgressChanged;
if (handler != null)
handler(this, new ProgressChangedEventArgs { CurrentProgress = progress });
}

private void DoLotsOfWork(object data)
{
// Достаем FileStream
FileStream stream = data as FileStream;
if (stream == null)
throw ArgumentException("Надо было все-таки передать нормальный FileStream", "data");

OnProgressChanged(0);

// Делаем один кусок работы, скажем, четверть, после чего сообщаем об этом "наверх"
...
OnProgressChanged(25);

// Делаем еще один кусок, скажем, уже 2/3 работы сделано
...
OnProgressChanged(66);

//Ну и вроде как все доделали
...
OnProgressChanged(100);
}

public Thread DoLotsOfWorkAsync(FileStream stream)
{
Thread thread = new Thread(new ParameterizedThreadStart(this.DoLotsOfWork));
thread.Start(stream);

return thread;
}
}
Соответственно, использоваться это добро будет примерно так:
Код:
WorkingClass wc = new WorkingClass();
wc.ProgressChanged += delegate (object sender, ProgressChangedEventArgs e)
{
if (progressBar.InvokeRequired)
progressBar.Invoke(delegate (int progress) { progressBar.Value = progress; },
new Object[] { e.CurrentProgress });
else
progressBar.Value = e.CurrentProgress;
};

FileStream stream = ...;
ws.DoLotsOfWorkAsync(stream);

Спасибо!
Дело то все в том, что работа зависит от размера файла, то есть я не могу точно указать на каком участке метода сделано определенное количество работы,
так как файл разбивается на части, методы работают по несколько раз
 
L

LuMee

Дело то все в том, что работа зависит от размера файла, то есть я не могу точно указать на каком участке метода сделано определенное количество работы,
так как файл разбивается на части, методы работают по несколько раз
Если файл разбивается на части, то события изменения прогресса можно пулять после обработки очередной части, если количество частей заранее известно. Если файл обрабатывается построчно/побайтно, то можно получить его размер перед началом обработки и сообщать о прогрессе по мере считывания очередного фрагмента.
Вероятно, в конечном итоге не получится абсолютно точное отображение прогресса, но это, как правило, и не нужно: главное, что пользователь уже видит, что программа что-то делает и примерно может оценить, сколько времени это займет.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!