Наличие оконной формы при обработке - PullRequest
0 голосов
/ 27 января 2010

Я делаю приложение, которое выполняет какое-то сканирование (оно проверяет наличие URL-адресов через короткий список) и, в зависимости от результата, добавляет в тот или иной список. если он существует, он переходит к lstOK, иначе он переходит к lst404.

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

Можно ли по-прежнему использовать форму и обновлять списки на ходу?

Это должно быть просто, я просто не знаю (пока)

Я использую C # в Visual Studio

- [обновление] -
Вся проверка URL находится в одной функции Start ()

Ответы [ 4 ]

4 голосов
/ 27 января 2010

попробуйте фоновый рабочий

2 голосов
/ 27 января 2010

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

Или вы могли бы сделать что-то вроде этого:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace ThreadWithDataReturnExample
{
    public partial class Form1 : Form
    {
        private Thread thread1 = null;

        public Form1()
        {
            InitializeComponent();

            thread1 = new Thread(new ThreadStart(this.threadEntryPoint));
            Thread1Completed += new AsyncCompletedEventHandler(thread1_Thread1Completed);
        }

        private void startButton_Click(object sender, EventArgs e)
        {
            thread1.Start();
            //Alternatively, you could pass some object
            //in such as Start(someObject);
            //With apprioriate locking, or protocol where
            //no other threads access the object until
            //an event signals when the thread is complete,
            //any other class with a reference to the object 
            //would be able to access that data.
            //But instead, I'm going to use AsyncCompletedEventArgs 
            //in an event that signals completion
        }

        void thread1_Thread1Completed(object sender, AsyncCompletedEventArgs e)
        {
            if (this.InvokeRequired)
            {//marshal the call if we are not on the GUI thread                
                BeginInvoke(new AsyncCompletedEventHandler(thread1_Thread1Completed),
                  new object[] { sender, e });
            }
            else
            {
                //display error if error occurred
                //if no error occurred, process data
                if (e.Error == null)
                {//then success

                    MessageBox.Show("Worker thread completed successfully");
                    DataYouWantToReturn someData = e.UserState as DataYouWantToReturn;
                    MessageBox.Show("Your data my lord: " + someData.someProperty);

                }
                else//error
                {
                    MessageBox.Show("The following error occurred:" + Environment.NewLine + e.Error.ToString());
                }
            }
        }

        #region I would actually move all of this into it's own class
            private void threadEntryPoint()
            {
                //do a bunch of stuff

                //when you are done:
                //initialize object with data that you want to return
                DataYouWantToReturn dataYouWantToReturn = new DataYouWantToReturn();
                dataYouWantToReturn.someProperty = "more data";

                //signal completion by firing an event
                OnThread1Completed(new AsyncCompletedEventArgs(null, false, dataYouWantToReturn));
            }

            /// <summary>
            /// Occurs when processing has finished or an error occurred.
            /// </summary>
            public event AsyncCompletedEventHandler Thread1Completed;
            protected virtual void OnThread1Completed(AsyncCompletedEventArgs e)
            {
                //copy locally
                AsyncCompletedEventHandler handler = Thread1Completed;
                if (handler != null)
                {
                    handler(this, e);
                }
            }
        #endregion

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

Application.DoEvents (); будет делать все события, которые произошли до этого момента. Например, после проверки каждого веб-сайта. do Application.DoEvents (); с другой стороны, если вы просто хотите обновить свои списки, это будет listboxname.Refresh ();
оба эти варианта, однако, все равно будут зависать, пока веб-сайт проверяется, если вы не выполняете много из них, чего я не предлагаю.
оба метода также используют только один поток и очень линейны.
Наилучшим вариантом будет создание нового потока для выполнения тестов или использование фонового рабочего, который может выполнять тесты в отдельном потоке, чтобы события формы могли обрабатываться мгновенно без необходимости ждать.

Ручное управление другим потоком не должно быть слишком сложным. вот пример.

using System.Threading;

public class MultiThreadingClass
{
    private void FunctionForNewThread()
    {
    //do stuff
    }

    private void FunctionWithParameter(object param)
    {
    //Should do checks with typeof() on param before casting
    int convertedparam = (int)param;
    //do stuff
    }
    Thread t, t2;
    static void Main()
    {
        ThreadStart ts = new ThreadStart(FunctionForNewThread);
        t = new Thread(ts);
        t.Start();
        int x = 5;
        ParameterizedThreadStart pts = new ParameterizedThreadStart(FunctionWithParameter);
        t2 = new Thread(pts);
        t2.Start(x);
    }
}

здесь может быть важно отметить, что вы никогда не должны добавлять Thread как локальную переменную, которая исчезнет, ​​так как вы можете действительно вернуть экземпляр потока, только выполнив Thread.CurrentThread в функции, которая была вызвана новым потоком. , но если этот поток уже заблокирован, у вас есть небольшая проблема:)

Чтобы легко обрабатывать потоки в глобальной переменной, либо создайте массив потоков, и вызовите Thread.Abort (); в каждом запущенном потоке, когда программа закрывается, или используйте класс ThreadPool в System.Threading.

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

Если это веб-форма, загляните в AJAX.NET. Есть несколько элементов управления (UpdatePanel - один из них), которые помогут вам сделать это.

Взгляните на инструментарий .

РЕДАКТИРОВАТЬ: только для веб-приложений.

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