Ошибка при запуске нового потока и открытии диалога с помощью Mono API - PullRequest
1 голос
/ 30 апреля 2011

Я работаю над родной dll, написанной на C ++, которая использует моно для отображения графического интерфейса пользователя.Я написал простой скелет, он работает, но при определенных условиях я получаю ошибку.

Сначала приведу код C #, который я вызываю из Mono API

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Threading;

namespace testApp
{
    static class Program
    {
        // This creates a new thread and runs dialog() on it, 
        // which opens a dialog window
        static void start()
        {
            Console.WriteLine("Running thread in Mono");
            Thread t = new Thread(new ThreadStart(dialog));
            t.Start();
        }

        public static void dialog()
        {
            Form f = new Form();
            f.ShowDialog();
            f.Dispose();
        }
    }
}

.скомпилирован как testApp.dll

В своем коде C / C ++ я делаю следующее:

  1. Загрузка сборки
  2. Найдите метод start () и запустите его
  3. введите бесконечный цикл, который считывает ввод с консоли
  4. , когда получена входная строка «open», снова запустите start ()

Теперь, в начале,форма открывается, она работает (не останавливается на экране, так как работает в своем собственном потоке), и я могу открыть больше экземпляров формы, набрав «open» в командной строке.Исключение выдается только тогда, когда я закрываю все открытые формы и затем пытаюсь открыть новую (снова нажимая «открыть» после закрытия ВСЕХ открытых форм).

Unhandled Exception: System.OutOfMemoryException: Not enough memory to complete operation [GDI+ status: OutOfMemory]
  at System.Drawing.GDIPlus.CheckStatus (Status status) [0x00000] in <filename unknown>:0
  at System.Drawing.Graphics.FromHwnd (IntPtr hwnd) [0x00000] in <filename unknown>:0
  at System.Windows.Forms.XplatUIWin32.GetAutoScaleSize (System.Drawing.Font font) [0x00000] in <filename unknown>:0
  at System.Windows.Forms.XplatUI.GetAutoScaleSize (System.Drawing.Font font) [0x00000] in <filename unknown>:0
  at System.Windows.Forms.Form.GetAutoScaleSize (System.Drawing.Font font) [0x00000] in <filename unknown>:0
  at System.Windows.Forms.Form..ctor () [0x00000] in <filename unknown>:0
  at (wrapper remoting-invoke-with-check) System.Windows.Forms.Form:.ctor ()
  at testApp.Program.dialog () [0x00000] in <filename unknown>:0
  at System.Threading.Thread.StartUnsafe () [0x00000] in <filename unknown>:0

Можете ли вы помочь мне расшифровать это сообщение?:)

каким-то образом, когда я закрываю последнее окно формы, я полагаю, что mono решает выгрузить / закрыть некоторый критический компонент, который не позволяет мне открыть другое окно после этого момента времени.мой C ++ (ну, на самом деле, C) код, который я использую:

#define _CRT_SECURE_NO_WARNINGS

#include <mono/jit/jit.h>
#include <mono/metadata/object.h>
#include <mono/metadata/environment.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/debug-helpers.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

static void runThread(MonoDomain* domain, MonoAssembly* assembly)
{
    MonoImage* image = mono_assembly_get_image (assembly);

    MonoClass *klass;
    MonoObject *obj;
    MonoMethod *m = NULL, *start = NULL;
    void* iter = NULL;
    klass = mono_class_from_name (image, "testApp", "Program");

    // Find method start()
    while ((m = mono_class_get_methods (klass, &iter))) 
    {
        if (strcmp (mono_method_get_name (m), "start") == 0) 
        {
            start = m;
            break;
        }
    }

    mono_runtime_invoke (start, NULL, NULL, NULL);
}

int main(int argc, char* argv[])
{
    MonoDomain *domain;
    const char *file;
    int retval;

    if (argc < 2)
    {
        fprintf (stderr, "Please provide an assembly to load\n");
        return 1;
    }

    file = argv [1];
    domain = mono_jit_init (file);
    MonoAssembly *assembly;
    assembly = mono_domain_assembly_open (domain, file);

    if (!assembly)
    {
        printf("Can not load assembly");
        exit (2);
    }

    // open dialog
    runThread(domain, assembly);

    // endless loop
    char *p = new char[100];
    while(1)
    {
        gets (p);

        // Open another dialog
        if( strcmp(p, "open") == 0)
            runThread(domain, assembly);
    }

    retval = mono_environment_exitcode_get ();
    mono_jit_cleanup (domain);
    return retval;
}

1 Ответ

1 голос
/ 04 мая 2011

После более подробного изучения я могу с уверенностью сказать, что это ошибка в Mono. Я отправил сообщение об ошибке по этому вопросу.

Это не было проблемой в отношении C API, поскольку я смог воссоздать ошибку только в коде C #. При первом открытии формы в новом потоке Mono выполняет определенную работу по инициализации. Если этот поток перестает работать или заканчивается, то некоторые ссылки на все, что потеряно, и любые вызовы, которые открывают формы или диалоговые окна после этого, завершатся неудачей. Это неожиданное и нежелательное поведение.

...