Запустите метод в потоке, так как он очень медленный - PullRequest
0 голосов
/ 12 января 2012

Если у меня есть метод, который возвращает строку следующим образом:

 public string ExecuteCommandSync(object command)
        {
            string result = "";
            try
            {
                System.Diagnostics.ProcessStartInfo procStartInfo =
                    new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);


                procStartInfo.RedirectStandardOutput = true;
                procStartInfo.UseShellExecute = false;

                procStartInfo.CreateNoWindow = true;

                System.Diagnostics.Process proc = new System.Diagnostics.Process();
                proc.StartInfo = procStartInfo;
                proc.Start();

                result = proc.StandardOutput.ReadToEnd();

                Console.WriteLine(result);
            }
            catch (Exception objException)
            {
                MessageBox.Show("error : " + objException.Message);
            }

            return result;
        } 

Теперь это работает нормально для небольших данных, но если у меня большие данные, они зависают ..

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

Может кто-нибудь помочь, пожалуйста.

спасибо

РЕДАКТИРОВАТЬ:

Это приложение c winform c #, работающее в Windows 7. По сути, идея состоит в том, чтобы вызвать команду cmd и запустить команду ... Это ошибка, которую я получаю при запуске из visual studio:

The CLR has been unable to transition from COM context 0x8d85c0 to COM context 0x8d8730 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this problem, all single threaded apartment (STA) threads should use pumping wait primitives (such as CoWaitForMultipleHandles) and routinely pump messages during long running operations.

РЕДАКТИРОВАТЬ 2 :: Хорошо, вот что я сделал до сих пор

public string ExecuteCommandSync(object command)
        {
            string result = "";
            try
            {

                backgroundWorker1.RunWorkerAsync(command);
            }
            catch (Exception objException)
            {
                MessageBox.Show("error : " + objException.Message);
            }

            return result;
        }
  private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            string result;
            Thread.Sleep(300);
            object command = (object)e.Argument;
            System.Diagnostics.ProcessStartInfo procStartInfo =
                   new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);


            procStartInfo.RedirectStandardOutput = true;
            procStartInfo.UseShellExecute = false;

            procStartInfo.CreateNoWindow = true;

            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            proc.StartInfo = procStartInfo;
            proc.Start();

            result = proc.StandardOutput.ReadToEnd();
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            results = (string)e.Result;
        }

и затем я вызываю его, используя:

string result1 = ExecuteCommandSync(command);

Ответы [ 4 ]

4 голосов
/ 12 января 2012
            result = proc.StandardOutput.ReadToEnd();

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

Потоки - действительно ваше решение, просто переместите этот код в обработчик событий DoWork для BackgroundWorker. Прочитайте эту страницу MSDN для получения рекомендаций.

2 голосов
/ 12 января 2012

Добавить в вашу программу:

BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.RunWorkerAsync();

А также:

void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    string result = (string)e.Result;
    //do what you need with it.
}

void bw_DoWork(object sender, DoWorkEventArgs e)
{
    //do your work here
    e.Result = yourResult;
}

Но также имейте в виду то, что говорили другие: поток не будет работать быстрее, чем не поточныйпрограмма.Преимущество будет в том, что программа не будет "зависать".

0 голосов
/ 12 января 2012

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

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

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

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

0 голосов
/ 12 января 2012

Вы можете использовать событие. Когда ваша thead закончила, она генерирует событие и дает String этому событию.

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