Ошибка компиляции C#: “Вызовите, или BeginInvoke нельзя назвать на управлении, пока дескриптор окна не был создан”.

Сеттер не должен заботиться о том, когда и сколько раз он вызывается извне. Если вы не хотите показывать setTimeLimit() вне класса и хотите, чтобы он вызывался только один раз за итерацию, тогда как насчет принятия списка «чего-то», а не одного «чего-то».

т.

public class MyClass {

    public void setSomethings(List<String> somethings) {
        setTimeLimit();
        somethings.forEach(this::setSomething);
    }

    private void setSomething(String something) {
        // ...
    }

    private void setTimeLimit() {
        // ...
    }
}

Таким образом, MyClass получает требуемый элемент управления, не нарушая функциональных отношений между MyClass и его потребителями.

8
задан OneShot 4 February 2009 в 22:24
поделиться

7 ответов

Право, я собираюсь запуститься снова.

Для понимания то, что происходит, необходимо понять, как.NET и Windows касаются друг друга..NET работает на Windows и переносит многие из собственного компонента, понятий Win32 как окно, listview, editbox (название Win32 стандартного текстового поля). Это означает, что Вы можете иметь допустимый экземпляр.NET TextBox или Формы, но не иметь базовую версию Windows того объекта (EditBox или Окно) все же. Когда HandleCreated верен, версия Windows объекта создается.

Ваша проблема происходит, потому что что-то является ведущим к logAdd методу, называемому, прежде чем Окно Формы было создано. Это означает где-нибудь во время Вашего запуска после того, как экземпляр Формы инстанцировали, но прежде чем дескриптор Окна был создан, что-то пытается назвать logAdd. Если Вы добавляете точку останова к logAdd, необходимо смочь видеть то, что делает тот вызов. То, что Вы найдете, - то, что вызов выполняется на Основном экземпляре, который Вы создаете в своем классе регистратора а НЕ Основном экземпляре, который на самом деле работает. Поскольку экземпляр регистратора никогда не показывают, дескриптор окна не создается, и таким образом, Вы получаете свою ошибку.

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

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

public partial class Main : Form
{
    private static Main mainFormForLogging;
    public static Main MainFormForLogging
    {
        get
        {
            return mainFormForLogging;
        }
    }

    public Main()
    {
        InitializeComponent();

        if (mainFormForLogging == null)
        {
            mainFormForLogging = this;
        }
    }

    protected void Dispose(bool disposing)
    {
         if (disposing)
         {
             if (this == mainFormForLogging)
             {
                mainFormForLogging = null;
             }
         }

         base.Dispose(disposing);
    }
}
12
ответ дан 5 December 2019 в 05:34
поделиться

Это - ошибка периода выполнения, не ошибка компилятора.

Ваша Форма, "Основная", должна быть отображена (следовательно созданный дескриптор окна), прежде чем можно будет выполнить вызовы к BeginInvoke или Вызвать на него.

То, что я обычно делаю в этих ситуациях, является отпуском это до Формы, чтобы определить, должно ли это использовать вызов для BeginInvoke или Вызвать. Можно протестировать это с вызовом к InvokeRequired (проверьте MSDN).

Таким образом для начинающих, я избавился бы от вызова logAddDelegate в updateLog методе класса Loggin. Просто выполните прямой вызов к форме для добавления журнала. Как так:

public partial class Main : Form
{
    public Main()
    {
        InitializeComponent();
    }

    private delegate void AddNewLogMessageEventHandler(string message);

    public void AddLogMessage(string message)
    {
        object[] args = new object[1];
        args[0] = message;

        if (InvokeRequired)
            BeginInvoke(new AddNewLogMessageEventHandler(AddLog), args);
        else
            Invoke(new AddNewLogMessageEventHandler(AddLog), args);
    }

    private void AddLog(string message)
    {
        this.Log.Items.Add(message);
    }
 }

}

Таким образом, Вы видите, сама Форма отвечает за определение, если это должно назвать метод асинхронно или нет.

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

2
ответ дан 5 December 2019 в 05:34
поделиться

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

В WinForms элементы GUI имеют две полуавтономных жизни: как классы в памяти и как объекты в операционной системе. По сути, возможно сослаться на управление в .NET, который еще не был на самом деле создан. "Дескриптор, создаваемый", посылает к присваиванию числа к управлению ОС позволить программам управлять своими свойствами.

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

2
ответ дан 5 December 2019 в 05:34
поделиться

Я решил это в прошлом использовании следующего метода:

private void invokeOnFormThread(MethodInvoker method)
{
    if (IsHandleCreated)
         Invoke(new EventHandler(delegate { method(); }));
    else
        method();
}

Звонить invokeOnFormThread вместо Вызывают. Это будет только использовать поток формы, если дескриптор был уже создан, иначе это будет использовать поток вызывающей стороны.

12
ответ дан 5 December 2019 в 05:34
поделиться

Та ошибка имеет тенденцию происходить, если Вы вызываете на окно, которое еще не 'показали'. Вы уверены, что не создаете второй экземпляр основного класса с Вашим кодом в Регистрирующемся классе (а именно, первая строка)? Может случиться так, что основная форма, которую Вы называете входом в систему, НЕ является основной формой, на которую Вы смотрите. Если Вы хотите проверить, добавьте вызов к "MainClass. Покажите ()" только в Вашем вызове входа. Если Вы получаете вторую копию основного появления формы, то проблема состоит в том, что Ваш класс входа не ссылается на правильный 'экземпляр' Вашей формы.

Думайте о классе как о 'проекте'. Каждый экземпляр класса (созданный с 'новым' словом) является другим объектом, созданным из проекта. Просто, потому что два объекта (в этом случае, Ваши две основных формы) совместно используют тот же проект, не означает, что можно использовать их попеременно. В этом случае у Вас уже есть основная форма, и Вы хотите 'снова использовать' ее. Можно попробовать:

MainClass myMainForm = Application.OpenForms.OfType<MainClass>().First();
logAddDelegate = myMainForm.logAdd; 
logAddDelegate(message);

в Вашей функции журнала вместо того, что Вы в настоящее время имеете. Различие то, что вызов к Приложению. OpenForms. OfType ().First войдет в Ваше приложение и получит ФАКТИЧЕСКУЮ основную форму, которую Вы видите (технически, он получит первую инстанцию его), и сделайте свой вызов на той форме, непосредственно.

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

1
ответ дан 5 December 2019 в 05:34
поделиться

logAddDelegate (сообщение);

Я думаю, что Вы называете это, прежде чем событие Form_Load было сгенерировано. Исправьте свой код для ожидания формы для загрузки прежде, чем назвать logAddDelegate (...) т.е. прежде, чем назвать Logging.updateLog ()

0
ответ дан 5 December 2019 в 05:34
поделиться

Этот Ваш точный код? Вы звоните this.Log.Items.Add(message); в Вашем добавлять (представляют метод в виде строки), но Ваш класс входа называют, Регистрируясь, не Журнал. Вы получили другую форму под названием Журнал, возможно? Если та форма не была создана при вызове добавить метода Вы получите это исключение.

0
ответ дан 5 December 2019 в 05:34
поделиться
Другие вопросы по тегам:

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