Как я реализую индикатор выполнения в C#?

Думайте, что лучше стать более конкретным, а не общим с подобными вопросами.

К Вашему вопросу, я не думаю, что он испорчен, но Вы правы, что он не может обратиться к некоторым. Однако, как только люди получают его, поскольку в понимают его, тогда они могут прибыть для использования его больше. Это - конечно, лучшая вещь должным быть помнить меньше паролей, поскольку каждый заканчивает создание их более слабый, чем они должны быть.

20
задан George Stocker 27 October 2010 в 18:11
поделиться

5 ответов

Некоторым это может не понравиться, но я этим занимаюсь:

private void StartBackgroundWork() {
    if (Application.RenderWithVisualStyles)
        progressBar.Style = ProgressBarStyle.Marquee;
    else {
        progressBar.Style = ProgressBarStyle.Continuous;
        progressBar.Maximum = 100;
        progressBar.Value = 0;
        timer.Enabled = true;
    }
    backgroundWorker.RunWorkerAsync();
}

private void timer_Tick(object sender, EventArgs e) {
    if (progressBar.Value < progressBar.Maximum)
        progressBar.Increment(5);
    else
        progressBar.Value = progressBar.Minimum;
}

Для стиля Marquee требуется, чтобы были включены VisualStyles, но он непрерывно прокручивается сам по себе, не требуя обновления. Я использую это для операций с базой данных, которые не сообщают об их ходе.

18
ответ дан 29 November 2019 в 23:44
поделиться

Когда вы выполняете операции в фоновом потоке и хотите обновить пользовательский интерфейс, вы не можете вызывать или устанавливать что-либо из фонового потока. В случае WPF вам понадобится Dispatcher.BeginInvoke, а в случае WinForms вам понадобится метод Invoke.

WPF:

// assuming "this" is the window containing your progress bar..
// following code runs in background worker thread...
for(int i=0;i<count;i++)
{
    DoSomething();
    this.Dispatcher.BeginInvoke((Action)delegate(){
         this.progressBar.Value = (int)((100*i)/count);
    });
}

WinForms:

// assuming "this" is the window containing your progress bar..
// following code runs in background worker thread...
for(int i=0;i<count;i++)
{
    DoSomething();
    this.Invoke(delegate(){
         this.progressBar.Value = (int)((100*i)/count);
    });
}

для делегата WinForms может потребовать некоторого преобразования или вам может потребоваться небольшая помощь, не помните точный синтаксис.

6
ответ дан 29 November 2019 в 23:44
поделиться

Идея отчета о ходе выполнения с фоновым рабочим процессом заключается в отправке события «процент выполнения». Вы сами несете ответственность за то, чтобы каким-то образом определить, «сколько» работы было выполнено. К сожалению, это часто самая сложная часть.

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

  • Определите, сколько строк нужно получить (SELECT COUNT (*) FROM ...)
  • Разделите фактическое чтение на более мелкие порции, сообщая о прогрессе каждый раз, когда один кусок завершен:

     for (int i = 0; я <количество; я ++)
    {
     bgWorker.ReportProgress ((100 * я) / счетчик);
     // ... (считываем данные для шага i)
    }
    
5
ответ дан 29 November 2019 в 23:44
поделиться

Я не скомпилировал это, поскольку это предназначено для подтверждения концепции. Вот как я реализовал индикатор выполнения для доступа к базе данных в прошлом. В этом примере показан доступ к базе данных SQLite с использованием модуля System.Data.SQLite

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{   
    // Get the BackgroundWorker that raised this event.
    BackgroundWorker worker = sender as BackgroundWorker;
    using(SQLiteConnection cnn = new SQLiteConnection("Data Source=MyDatabase.db"))
    {
        cnn.Open();
        int TotalQuerySize = GetQueryCount("Query", cnn); // This needs to be implemented and is not shown in example
        using (SQLiteCommand cmd = cnn.CreateCommand())
        {
            cmd.CommandText = "Query is here";
            using(SQLiteDataReader reader = cmd.ExecuteReader())
            {
                int i = 0;
                while(reader.Read())
                {
                    // Access the database data using the reader[].  Each .Read() provides the next Row
                    if(worker.WorkerReportsProgress) worker.ReportProgress(++i * 100/ TotalQuerySize);
                }
            }
        }
    }
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    this.progressBar1.Value = e.ProgressPercentage;
}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // Notify someone that the database access is finished.  Do stuff to clean up if needed
    // This could be a good time to hide, clear or do somthign to the progress bar
}

public void AcessMySQLiteDatabase()
{
    BackgroundWorker backgroundWorker1 = new BackgroundWorker();
    backgroundWorker1.DoWork += 
        new DoWorkEventHandler(backgroundWorker1_DoWork);
    backgroundWorker1.RunWorkerCompleted += 
        new RunWorkerCompletedEventHandler(
    backgroundWorker1_RunWorkerCompleted);
    backgroundWorker1.ProgressChanged += 
        new ProgressChangedEventHandler(
    backgroundWorker1_ProgressChanged);
}
2
ответ дан 29 November 2019 в 23:44
поделиться

Если вы не можете знать прогресс, вам не следует подделывать его, злоупотребляя индикатором выполнения, вместо этого просто отобразите какой-то значок занятости, например en.wikipedia. org / wiki / Throbber # Spinning_wheel Показывать при запуске задачи и скрывать, когда она завершена. Это сделало бы графический интерфейс более «честным».

11
ответ дан 29 November 2019 в 23:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: