Вопрос о методе потоков - PullRequest
4 голосов
/ 23 июля 2010

Я использую следующий метод для отображения немодального окна сообщений.

public void ShowMessageBox(string Message)
{
  var thread = new Thread(
    () =>
    {
      MessageBox.Show(Message);
    });
  thread.Start();
}

"() => {...}" - это то, чего я никогда раньше не видел.Как называется этот кодовый шаблон?

Кроме того, thread.Start запускает поток и автоматически закрывается после завершения метода "() => {...}" (когда окно сообщения исправно), верно?Если да, не могли бы вы указать мне какую-нибудь официальную документацию о том, что тема закрывается автоматически?

Спасибо!

Ответы [ 5 ]

7 голосов
/ 23 июля 2010

Это лямбда-оператор, и читается как «идет».В MSDN есть хорошее введение: Лямбда-выражения (Руководство по программированию в C #)

Одна из проблем, связанных с вашим примером, заключается в том, что вы запускаете новый поток для обновления пользовательского интерфейса, пользовательский интерфейс по своей сути единичный.Это связано с тем, что фоновые обновления обычно не подходят (если вы вручную / явно не проверяете InvokeRequired и не вызываете Invoke() при необходимости.


Что касается потоков в пользовательском интерфейсе ...

В WinForms каждый Form или Control создается в определенном потоке («потоке пользовательского интерфейса»), и вы можете думать о том, что этот поток является владельцем этого элемента управления (не совсем правильный, но хороший способосмыслить это). Обновление пользовательского интерфейса из этого потока является безопасным, обновление пользовательского интерфейса из другого потока создает риск коллизий и повреждения, а также всех обычных рисков параллельного / асинхронного программирования.

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

Вот пример: вы должны быть в состоянии вставить это в код новой формы с помощью кнопки и текстового поля.

Для использования:

  • Попробуйте закомментировать либо вызов SetTextAsyncSafe(), либо SetTextAsyncSafe() - выполняетсяоба могут сбить вас с толку, поскольку они не обязательно будут выполняться в том порядке, в котором они называются (они работают асинхронно, помните?).

  • Затем установите точку останова на SetText().Вы должны увидеть, что «безопасный» вызов на самом деле вызовет метод дважды - первый вызов обнаружит InvokeRequired и во второй раз вызовет метод для правильного потока при Invoke() обращении к нему.

  • Вы должны увидеть исключение, которое выдается, когда SetTextAsyncUnsafe() фактически получает операторы textBox1.Text = value;.Исключением будет InvalidOperationException с сообщением «Операция в нескольких потоках недопустима» - вы можете использовать этот термин в Google для получения более подробной информации.

Код:

private void button1_Click(object sender, EventArgs e)
{
  SetTextAsyncSafe("This update was made from the UI Thread by using Invoke()");
  SetTextAsyncUnsafe("This update was made directly from the background thread and can cause problems");
}

private void SetTextAsyncUnsafe(string value)
{
  new Thread(() => SetText(value, false)).Start();
}

private void SetTextAsyncSafe(string value)
{
  new Thread(() => SetText(value, true)).Start();
}

private void SetText(string value, bool checkInvokeRequired)
{
  if (checkInvokeRequired) 
  {
    if (InvokeRequired) 
    {
      Invoke(new Action(() => SetText(value, checkInvokeRequired)));
      return; // early exit
    }
  }

  textBox1.Text = value;
}
3 голосов
/ 23 июля 2010

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

Это (почти) эквивалент:

public void ShowMessageBox(string Message)
{
    var thread = new Thread(ShowBox);
    thread.Start(Message);
}

public void ShowBox(object message)
{
    MessageBox.Show(message.ToString());
}
2 голосов
/ 23 июля 2010

Лямбда-выражение, функция C # версии 3.

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

Это может плохо работать, когда пользователь работает в окне приложения или переключает фокус на другое приложение,окно сообщения исчезает за окном переднего плана.У пользователя нет очевидного способа сказать, что он там есть, он просто упустит его из виду.Могут пройти часы, если не дни, прежде чем она найдет его обратно.Тем временем этот поток потребляет ресурсы ужасно, вы, вероятно, никогда бы об этом не узнали, если бы знали, что для этого окна сообщений требуется мегабайт памяти.В крайних случаях вы можете вызвать сбой программы с помощью OOM.

Общая альтернатива в программировании пользовательского интерфейса Windows - всплывающая подсказка, предоставляемая NotifyIcon.Или ваша собственная форма со свойством TopMost, установленным в True, поэтому она не может легко потеряться.Также позволяет контролировать положение, важное для «немодальных» уведомлений, которые не должны мешать.Установите для свойства ShowWithoutActivation этой формы значение true в конструкторе формы, чтобы оно не захватывало фокус.

2 голосов
/ 23 июля 2010

Это называется лямбда-выражением.Вы можете прочитать больше здесь .

1 голос
/ 23 июля 2010

Это оператор лямбда .

Да, поток активен, пока работает этот анонимный метод.Поскольку после MessageBox.Show () нет других операторов, поток завершит работу, и это должно быть правдой ... если у вас есть сомнения, добавьте это перед запуском:

thread.Name = "LALALA";

и затем отладьте ваше приложение.Когда появится окно с сообщением, приостановите выполнение, перейдите в Просмотр потоков, и вы увидите, что LALALA работает.Нажмите OK и снова сделайте паузу, не должно быть «LALALA» ... =)

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