Класс с DataReceivedHandler не позволяет мне получить доступ в Основной форме и запустить таймер [дубликат]

Имейте в виду, что независимо от сценария причина всегда одинакова в .NET:

Вы пытаетесь использовать ссылочную переменную, значение которой Nothing / null. Если для ссылочной переменной значение Nothing / null, это означает, что на самом деле оно не содержит ссылку на экземпляр любого объекта, который существует в куче.

Вы либо никогда не присваивали какую-либо переменную, никогда не создавали экземпляр значения, присвоенного переменной, или вы вручную устанавливали переменную, равную Nothing / null, или вы вызывали функцию, которая установите для этой переменной значение Nothing / null.

8
задан Rob 3 May 2011 в 12:40
поделиться

6 ответов

При вызове метода к элементу управления, если вызывающий объект находится в другом потоке, чем тот, на котором был создан элемент управления, вам необходимо вызвать с помощью Control.Invoke . Вот пример кода:

// you can define a delegate with the signature you want
public delegate void UpdateControlsDelegate();

public void SomeMethod()
{
    //this method is executed by the background worker
    InvokeUpdateControls();
}

public void InvokeUpdateControls()
{
    if (this.InvokeRequired)
    {
        this.Invoke(new UpdateControlsDelegate(UpdateControls));
    }
    else
    {
        UpdateControls();
    }
}

private void UpdateControls()
{
    // update your controls here
}

Надеюсь, что это поможет.

9
ответ дан Daniel Peñalba 28 August 2018 в 08:40
поделиться

Вам нужно проверить, требуется ли Invoke для элемента управления, который вы пытаетесь обновить. Что-то вроде этого:

Action<Control, string> setterCallback = (toSet, text) => toSet.Text = text;

void SetControlText(Control toSet, string text) {
  if (this.InvokeRequired) {
    this.Invoke(setterCallback, toSet, text);
  }
  else {
    setterCallback(toSet, text);
  }
}
2
ответ дан AlexCuse 28 August 2018 в 08:40
поделиться

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

void UpdateWorker()
{
   //Here ddUser is the user control
   //Action to be performed should be called within { } as like below code
   if (this.ddUser.InvokeRequired)
      ddUser.Invoke(new MethodInvoker(() => { ddUser.Size = new Size(100, 100); }));
}
0
ответ дан Amal 28 August 2018 в 08:40
поделиться

Обновлено из Invoke, чтобы начать Invoke

// you can define a delegate with the signature you want
public delegate void UpdateControlsDelegate();

public void SomeMethod()
{
    //this method is executed by the background worker
    InvokeUpdateControls();
}

public void InvokeUpdateControls()
{
    if (this.InvokeRequired)
    {
        this.BeginInvoke(new UpdateControlsDelegate(UpdateControls));
    }
    else
    {
        UpdateControls();
    }
}

private void UpdateControls()
{
    // update your controls here
}
0
ответ дан Pankaj 28 August 2018 в 08:40
поделиться

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

    public delegate void InvocationDelegate();

    public void DoGuiStuff(){
      if (someControl.InvokeRequired){
        someControl.Invoke(InvocationDelegate(DoGuiStuff));
        return;  
      }

      //GUI manipulation here
    }

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

1
ответ дан Russell Troywest 28 August 2018 в 08:40
поделиться

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

Во многих повседневных .NET-программах явное создание потоков или вызов .Invoke - это признак того, что вы не используете фреймворк в полной мере (конечно, есть много законных причин делать вещи низкого уровня тоже, это просто, что они менее распространены, что люди иногда понимают).

3
ответ дан Will Dean 28 August 2018 в 08:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: