2011-03-11 2 views
2

Я столкнулся с действительно странной ситуацией. Это должно быть так просто, но я не уверен, почему это происходит.C# Progress Bar не сотрудничает

У меня есть индикатор выполнения marquee, установленный на visible = false, поскольку это начальное состояние. Затем в какой-то момент во время выполнения я вызываю одну из своих функций и прямо перед вызовом, я устанавливаю PB на visible = true, а после завершения функции я возвращаю ее в видимый = false. Тогда это не становится проще.

If (something) 
{ 
    pb.visible=true; 
    runMyfunction(x, x, x, x,); 
    pb.visible=false; 
} 

Проблема в том, что я никогда не вижу ПБ. Если я прокомментирую свою функцию и удалю = false, PB появится, но как только я верну свою функцию обратно, PB никогда не появится.

Я пробовал различные подходы. Используя инструкции If, чтобы убедиться, что я получаю индикатор выполнения до того, как он когда-либо касается функции, и он все еще удерживает PB.

Я что-то упустил? Это не похоже, что это должно быть так сложно. Показать объект, запустить функцию, скрыть объект. Правильно? :)

+4

Является ли это WinForms или asp.net или WPF или что? – kprobst

+0

Вы ссылаетесь на индикатор прогресса WinForms в ASP.NET? – TheBoyan

ответ

7

Моя догадка myRunFunction() работает на тему пользовательского интерфейса.

Попробуйте запустить его внутри BackgroundWorker и запустите ProgressBar перед вызовом RunWorkerAsync и остановите его в событии RunWorkerCompleted.

Отредактировано с примером кода:

public class SomeClass 
{ 
    private BackgroundWorker _myFunctionBackgroundWorker; 
    private SomeProgressBar pb; 

    public SomeClass() 
    { 
     _myFunctionBackgroundWorker = new BackgroundWorker(); 
     _myFunctionBackgroundWorker.DoWork += myFunctionBackgroundWorker_DoWork; 
     _myFunctionBackgroundWorker.RunWorkerCompleted += myFunctionBackgroundWorker_RunWorkerCompleted; 

     pb.visible = true; 
     _myFunctionBackgroundWorker.RunWorkerAsync(); 
    } 

    private void myFunctionBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     runMyfunction(); 
    } 


    private void myFunctionBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     pb.visible = false; 
    } 
} 
+0

Работал как шарм! Спасибо. Однако есть одна проблема. У моей функции есть несколько операторов catch, и когда они попадают в те, я получаю ошибку кросс-потоковой передачи. Я думаю, по какой-то причине они не инкапсулируются в исходную нить, начатую фоновым работником. В любом случае, я могу это исправить? – GeneK

+0

Ничего, я понял. Мне пришлось немного изменить свою функцию, но, пройдя все мои результаты до e.Result, все работает отлично! Еще раз спасибо за то, что я установил правильный подход, используя backgroundworker. – GeneK

2

внутри вашего runMyFunction() вызова метода Application.DoEvents(), чтобы заставить ваше приложение перерисовывать и обрабатывать петли окна сообщений:

например

void myRunFunction() 
{ 
    while (someFlag) 
    { 
    // do work 
    pb.Value = someValue; 
    Application.DoEvents(); 
    } 
} 
1

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

7

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

Вы можете сортировать работу по этому вызову, позвонив по телефону: Application.DoEvents Который перестает обрабатывать ваш метод достаточно долго, чтобы обрабатывать некоторые сообщения Windows (и делать соответствующий рисунок).

Большая проблема с Application.DoEvents является то, что если вы будете обновлять свой бар Прогресс от вашего runMyfunction() вы собираетесь придется постоянно звонить Application.DoEvents, чтобы ваш PB рисовать, или вы будете видеть это, но вы будете никогда не увидите обновления.

Лучшее решение - нажать на ваш runMyfunction() звонок в фоновый поток и обновить индикатор выполнения асинхронно оттуда. Это, конечно, намного сложнее, но обеспечивает лучший пользовательский интерфейс.

+0

BackgroundWorker может быть идеальным для этой ситуации. Он инкапсулирует множество методов, которые вам понадобятся. – ChrisG

+0

Это замечательно, так как оно решает проблему. Но, поскольку мое приложение все еще связано, а функция работает ~ 10 секунд, шатер никогда не перемещается.Я просто делаю простую маршрутизацию, показывающую область выделения во время выполнения функции, а затем удаляя ее в конце. Я собираюсь попробовать предложение ROBOlav с помощью фонового рабочего. – GeneK