C # Получение к исходной теме, чтобы установить значения текстового поля - PullRequest
1 голос
/ 22 марта 2012

У меня есть основная форма Form1, на которой выполняется основная часть моей программы.

У меня есть отдельный поток, который начал выполнять алгоритм.

Когда я запускаю метод из нового потока, метод MyAlgorithm() я получаю ошибку

InvalidOperationException с сообщением: «Имя элемента управления, доступ к которому получен из потока, отличного от потока, в котором он был создан».

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

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

// Reset the results values
public void ShowResults()
{
    while (true)
    {

        loopsNum.Text = Convert.ToString(resultLoopsNum);
        nodesVisitedNum.Text = Convert.ToString(resultNodesVisitedNum);
        nodesResolvedNum.Text = Convert.ToString(resultNodesResolvedNum);
        cpuLoopsNum.Text = Convert.ToString(resultCpuLoopsNum);
        shortestPathCostNum.Text = Convert.ToString(resultShortestPathCost);

    } 
}

Я смотрел на методы Invoke (), но не знаю, как получить исходный экземпляр моего Form1 из многопоточного метода.

Я вызываю свою ветку вот так ...

        // Set the algorithm method up in it's own thread
        Thread thread = new Thread(new ThreadStart(MyAlgorithm));

        // Run the algorithm
        thread.Start();

Ответы [ 4 ]

5 голосов
/ 22 марта 2012

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

В Windows Forms вы бы либо использовали Control.Invoke / BeginInvoke или использовали BackgroundWorker и выполнить обновление в обработчике событий прогресса.

В WPF вы бы использовали Dispatcher.Invoke / BeginInvoke.

В C # 5 и .NET 4.5 вы сможете использовать асинхронные методы, которые должны многое упростить ...

Я смотрел на методы Invoke (), но не знаю, как получить исходный экземпляр моего Form1 из многопоточного метода.

Если «потоковый метод» является просто методом экземпляра Form, то у вас уже есть ссылка this. Если это не так, вам нужно будет предоставить эту информацию - в идеале ISynchronizeInvoke, чтобы избежать прямой зависимости от Windows Forms, если вы можете выразить часть «обновление» отдельно. (Этот интерфейс несколько устарел в наши дни в пользу контекстов синхронизации, но он все еще отлично работает.)

2 голосов
/ 22 марта 2012

Посмотрите на Control.Invoke () :

public void ShowResults()
{
  while (true)
  {
    Thread.Sleep(1000); // don't spam the UI thread

    if (this.InvokeRequired) 
    {
      this.Invoke((Action)UpdateGui);
    }  
    else
    {
      UpdateGui();
    }
  } 
}

private void UpdateGui() 
{  
  loopsNum.Text = Convert.ToString(resultLoopsNum);
  nodesVisitedNum.Text = Convert.ToString(resultNodesVisitedNum);
  nodesResolvedNum.Text = Convert.ToString(resultNodesResolvedNum);
  cpuLoopsNum.Text = Convert.ToString(resultCpuLoopsNum);
  shortestPathCostNum.Text = Convert.ToString(resultShortestPathCost);
}
1 голос
/ 22 марта 2012

Здесь также есть другие варианты:

Альтернативно используйте System.Forms.Timer для периодического вызова ShowResults.Или другой вариант будет , а не , чтобы использовать другой поток для выполнения операции;сделайте это в потоке GUI и вызовите Application.DoEvents() изнутри операции, когда вы хотите разрешить обновление GUI.

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

1 голос
/ 22 марта 2012

Вы можете использовать:

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