Поток Безопасная альтернатива Thread.Sleep, которая позволяет активность браузера в C # - PullRequest
0 голосов
/ 01 декабря 2011

Мне нужна простая функция ожидания, которая позволяет обрабатывать события браузера и является поточно-ориентированной. Коллега сказал, что никогда не следует использовать DoEvents при работе с несколькими потоками.

Я замечаю, что когда я использую Thread.Sleep(10000);, моя активность в браузере приостанавливается до тех пор, пока сон не будет завершен.

Кто-нибудь может порекомендовать альтернативу?

Вот код для просмотра:

    public static int f_sleep(int time)
    {

        System.DateTime now = System.DateTime.Now;
        System.TimeSpan duration = new System.TimeSpan(0, 0, 0, time);
        System.DateTime then = now.Add(duration);


        Thread this_thread = Thread.CurrentThread;
        while (then > DateTime.Now)
        {
            //MessageBox.Show("NewTime:" + then + "Now:" + DateTime.Now);
            //we do not want to use this because it's said to mess up multithreading
            Application.DoEvents();

            //Thread.CurrentThread.Sleep(10);
            Thread.Sleep(10);
        }           

        return 1;
    }

    private void f_run_selected_campaigns(object sender, EventArgs e)
    {
        jobs_datagrid.EndEdit();

        int count_active = 0;
        foreach (DataGridViewRow row in jobs_datagrid.Rows)
        {

            //MessageBox.Show(row.Cells[1].Value.ToString());
            if (row.Cells[1].Value.ToString() == "True")
            {
                count_active++;



                //troubleshooting
                Thread this_thread = new Thread(() =>
                    this.Invoke((MethodInvoker)delegate
                    {
                        test("hello");
                    }
                ));

                //threading properties
                this_thread.Name = "thread_" + row.Cells[0].Value.ToString();
                this_thread.IsBackground = true;
                this_thread.Start();

            }

        }

        if (count_active == 0)
        {
            MessageBox.Show("No campaigns are selected!");

        }
    }

    private void test(string this_string)
    {

        MessageBox.Show(this_string);
        //Thread.Sleep(1000);
        f_sleep(10); //for some reason Thread.Sleep does not work well with my browser loading waiting so I drew this up to create a temp pause in the code logic, but it's causing my threads to not run asychronously
        MessageBox.Show("Thread Done");
    }

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

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

    private int WaitBrowserLoading(Control browser)
    {
        lock(_locker)
        {
            tabcontrol_browser.Invoke((MethodInvoker) delegate {
                for (int i = 0; i < 1000000; i++)
                {
                    if(((WebBrowser)browser).ReadyState != WebBrowserReadyState.Complete)
                    {
                        Application.DoEvents();
                        Thread.Sleep(10);
                    }else
                    {
                    break;
                    }
                } 

            });
            return 1;
        }

    }

    public static int f_sleep(int time)
    {
        System.DateTime now = System.DateTime.Now;
        System.TimeSpan duration = new System.TimeSpan(0, 0, 0, time);
        System.DateTime then = now.Add(duration);

        while (then > DateTime.Now)
        {
            Application.DoEvents();
            Thread.Sleep(10);
        }

        return 1;

    }

Ответы [ 6 ]

3 голосов
/ 01 декабря 2011

Никогда не используйте Thread.Sleep (), чтобы дождаться завершения чего-либо еще.

Если ваше приложение ожидает, пока элемент управления браузера завершит загрузку страницы или URL-адреса, вам следует перехватить событие в элементе управления браузератак что он скажет вам, когда он закончил загрузку.Вы не сказали, какой браузер вы используете, но поищите событие с именем «Loaded», «PageLoaded», «AfterNavigation» или что-то подобное.

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

2 голосов
/ 01 декабря 2011

Я не уверен, что именно вы ищете, но, возможно, это:

System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer();

public Form1()
{
    myTimer.Interval = 1000;
    myTimer.Tick += new EventHandler(myTimer_Tick);
    myTimer.Start();
    //Do stuff. 
}

void myTimer_Tick(object sender, EventArgs e)
{
    myTimer.Stop();
    //Do stuff when it ticks.
}
1 голос
/ 01 декабря 2011

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

1 голос
/ 01 декабря 2011

Это поможет?Он блокирует только ваш новый поток.

new Thread(() =>
{
    Thread.Sleep(10000);

    // do stuff
}).Start();

// and we're back, immediately

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

1 голос
/ 01 декабря 2011

Одной вещью, которая может сработать, если у вас есть контроль над контентом, обслуживаемым элементами управления браузера, является перенаправление с задержкой по времени. Предоставьте пользователю страницу, содержащую бесконечный цикл индикатора прогресса анимированного GIF и содержащую следующее:

<META HTTP-EQUIV="refresh" CONTENT="5;URL=my-next-page">

На этой странице будет отображаться индикатор прогресса, а через 5 секунд он будет перенаправлен на «my-next-page».

0 голосов
/ 01 декабря 2011

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

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