ProgressBar отдельная тема - PullRequest
       3

ProgressBar отдельная тема

1 голос
/ 30 января 2010

У меня есть вопрос о значении индикатора выполнения.

У меня есть основная тема

<code></p>

<p>private void button1_Click(object sender, EventArgs e) 
{ 
progress prog = new progress(); 
progress.progressEvent += new progress.progressEventHandler(progressEvent); 
for(int i=0;i<100;i++) 
{ 
Thread.Sleep(100); 
prog.incA(); 
} 
} </p>

<p>void progressEvent(object sender) 
{ 
if (progressBar1.InvokeRequired) 
{ 
//Tady mi to caka az kym nedobehne cyklus for a pak zacne tohleto fungovat 
progressBar1.Invoke(new ChangeProgressBarValue(ProgressStep)); 
} 
else 
{ 
ProgressStep(); 
} 
} </p>

<p>public void ProgressStep() 
{ 
progressBar1.PerformStep(); 
} </p>

<p>public class progress 
{ 
private ThreadStart ts; 
private Thread th; 
private bool status = true; 
public delegate void progressEventHandler(object sender); 
public static event progressEventHandler progressEvent; 
private int b,a = 0; </p>

<p>public progress() 
{ 
ts=new ThreadStart(go); 
th = new Thread(ts); 
th.IsBackground = true; 
th.Start(); 
} </p>

<p>public void incA() 
{ 
a++; 
if(a==100) 
status = false; 
} </p>

<p>private void go() 
{ 
while (status) 
{ 
if (a != b) 
{ 
b = a; 
if (progressEvent != null) 
progressEvent(this); 
} 
} 
th.Abort(); 
} 
} 

и моя проблема в том, ЕСЛИ запускать основной поток и вызывать IncA, это событие вызова метода, а в случае - вызывать прогрессбар и это вызывает ожидание завершения основного потока FOR

зачем ждать? ТНХ

Ответы [ 2 ]

6 голосов
/ 30 января 2010

Ваш цикл в главном потоке предотвращает события «рисования». Поскольку вы вызываете функцию индикатора выполнения из этого потока, вы никогда не увидите обновлений.

Вам нужно переместить код, чтобы полностью выполнить приращение к другому потоку.

Вот пример того, что вы хотите сделать, используя Button, BackgroundWorker и ProgressBar:

private void button1_Click(object sender, EventArgs e)
{
    backgroundWorker1.RunWorkerAsync();
}

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    for (int i = 1; i <= 100; i++)
    {
        backgroundWorker1.ReportProgress(i);
        Thread.Sleep(100);
    }
}

private void backgroundWorker1_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
    this.progressBar1.Value = e.ProgressPercentage;
}

Надеюсь, это поможет!

1 голос
/ 30 января 2010

Элемент управления индикатора выполнения является объектом пользовательского интерфейса и создается в потоке пользовательского интерфейса. Когда вы вызываете Invoke или BeginInvoke, чтобы обновить его, вы запрашиваете обновление пользовательского интерфейса.

Однако поток пользовательского интерфейса занят - в обработчике события CLick вашей кнопки есть цикл, который Sleep () отслеживает поток и вызывает prog.IncA в цикле. Таким образом, он никогда не возвращается обратно в основной цикл пользовательского интерфейса (который отправляет сообщения Windows и обновляет пользовательский интерфейс). Ваш индикатор выполнения является внутренним обновлением, но у него никогда не будет возможности перерисовать, потому что поток пользовательского интерфейса "занят".

Код «обработки» (то есть зацикливание и вызов prog.IncA ()) вообще не должен выполняться в потоке пользовательского интерфейса - его нужно запустить в отдельном потоке, а затем выйти из обработчика Click, чтобы Пользовательский интерфейс может продолжить обновление.

Обратите внимание, что это имеет побочный эффект - если ваш поток пользовательского интерфейса работает, то пользователь сможет продолжить взаимодействие с вашей программой, и поэтому он может снова нажать на кнопку и запустить другой фоновый поток - так что у вас есть быть очень осторожным, чтобы убедиться, что пользователь не может делать ничего «опасного» в пользовательском интерфейсе, пока вы заняты обработкой.

Я предлагаю вам взглянуть на некоторые учебные пособия по ознакомлению с потоками, чтобы получить представление о том, как использовать BackgroundWorker или другой механизм для запуска кода в отдельном потоке. Как только вы поймете это, вы можете добавить индикатор выполнения. (И обратите внимание, что хотя индикатор выполнения звучит как простейшая вещь, на самом деле это довольно сложно сделать из-за необходимости продолжения работы потока пользовательского интерфейса, но не позволяя пользователю делать что-либо опасное во время вашей обработки)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...