BackgroundWorker Вопрос (C # Windows Forms) - PullRequest
2 голосов
/ 18 марта 2011

Я нахожусь на MSDN, читая о классе BackgroundWorker, и у меня есть вопрос о том, как он работает.

В следующем коде есть цикл for. А внутри цикла for в предложении else вы должны:

Выполнить длительную операцию и сообщить о ходе выполнения.

Но почему существует петля for, и почему ее максимальное значение составляет всего 10?

private void bw_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;

    for (int i = 1; (i <= 10); i++)
    {
        if ((worker.CancellationPending == true))
        {
            e.Cancel = true;
            break;
        }
        else
        {
            // Perform a time consuming operation and report progress.
            System.Threading.Thread.Sleep(500);
            worker.ReportProgress((i * 10));
        }
    }
}

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

Ответы [ 5 ]

5 голосов
/ 18 марта 2011

Как я могу сделать этот фоновый рабочий отчет о прогрессе на основе запроса MySQL SELECT?

Ты не можешь. Это одна из проблем синхронного вызова метода, которая не позволяет заранее предсказать, сколько времени это займет. У вас есть две точки отсечения времени, чтобы иметь дело с. Прежде чем вызывать метод, а после вызывать метод. Вы не получаете ничего промежуточного. Либо метод вернулся, либо нет.

Вы можете использовать статистику в своих интересах, хотя. Вы можете записывать, сколько времени занимает каждый раз, когда он выполняется, сохранять его и использовать для расчета прогноза, но он никогда не будет точным. С таким прогнозом вы можете соответствующим образом распределить отчеты о прогрессе, чтобы в итоге вы получили 100% при статистическом прогнозе или около него, который вы рассчитали.

Однако, если база данных работает медленнее или быстрее, чем обычно, она будет отключена.

Также обратите внимание, что какой-либо поток, который вызывает MySQL для извлечения данных, не может быть тем же потоком, который сообщает о прогрессе, поскольку он будет «ожидать» базу данных MySQL и код .NET, который обращается к нему, чтобы вернуться с данные, все в одном куске. Вам нужно раскрутить еще одну ветку, которая сообщает о прогрессе.

2 голосов
/ 18 марта 2011

Но почему существует цикл for и почему его максимальное значение составляет всего 10?

В этом примере работник сообщает о прогрессе между 10 и 100, просто изпростота.Значения от 10 до 100 берутся из i (1-10) и * 10 в ReportProgress.

В документации сказано, что ReportProgress принимает:

Процент отОт 0 до 100 завершенной фоновой операции.

Когда вы пишете ее для своей действительно массивной базы данных, вы должны сообщать о прогрессе в процентах, от 0 до 100.

Принимая во внимание, что ваша база данных может занять «до минуты», 1% чуть больше, чем 1/2 секунды, поэтому вы должны видеть, что любой связанный индикатор прогресса перемещается каждые 1/2 секунды или около того.Это звучит как довольно плавный отчет для меня.

(Другие ответы описывают, почему трудно прикрепить прогресс к SQL-запросу)

1 голос
/ 18 марта 2011

Вам нужно будет найти способ измерить ход вашего запроса .Вместо одного длинного запроса вы можете выполнить его в пакетном режиме (скажем, 10, тогда прогресс будет увеличиваться на 10% каждый раз).

0 голосов
/ 18 марта 2011

Пример кода - это просто пример. Таким образом, 10 является произвольным. Это просто показывает пример оценки прогресса. В этом случае есть 10 отдельных шагов, поэтому он может легко оценить прогресс.

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

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

Что я делаю, это:

Предположим, что самое длительное время, которое потребуется, - это период ожидания соединения. Таким образом, если запрос завершится неудачно из-за разрыва соединения, пользователь получит совершенно точный индикатор выполнения. Большинство запросов занимают гораздо больше времени, чем значение тайм-аута, поэтому пользователь видит небольшой прогресс, а затем он неожиданно завершается. Это дает пользователю иллюзию, что все произошло лучше, чем ожидалось!

Для этого я выполняю Db-запрос асинхронно и запускаю индикатор выполнения с таймера пользовательского интерфейса, а не с помощью BackgroundWorker.

0 голосов
/ 18 марта 2011

В примере показано, как пакетировать длинные процессы, чтобы о них можно было сообщить.Инструкция «sleep» в этом примере будет заменена вызовом метода, который выполнил трудоемкое пакетное задание.

В вашем случае, если вы не можете разделить свой запрос на несколько частей, вы можетена самом деле не используйте ReportProgress для предоставления отзывов - у вас не будет никакого прогресса, чтобы сообщить.SQL-запрос - это однократный запуск, а ReportProgress используется для пакетных операций.

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

...