Поэтому я создал графический интерфейс Winforms в Visual Studio, используя C #, но для проекта, над которым я работаю, я хочу, чтобы большая часть кода была написана на Python. Я надеюсь, что «движок» будет написан на python (для переносимости), а затем я смогу поменять интерфейс приложения.

Я сделал проект C # для компиляции в .dll и смог импортировать классы в скрипт IronPython и нормально запустить графический интерфейс.

Проблема в том, что запуск GUI останавливает выполнение скрипта Python, если я не помещаю его в отдельный поток. Однако, если я помещаю графический интерфейс в отдельный поток и пытаюсь использовать исходный поток python для изменения информации о состоянии, я получаю исключение об изменении элемента управления из потока, отличного от того, который его создал.

Есть ли какой-нибудь хороший способ связи с потоком GUI или способ выполнить то, что я пытаюсь сделать?

Драйвер C # GUI:

public class Program
{
    private static MainWindow window;

    [STAThread]
    static void Main()
    {
        Program.RunGUI();
    }

    public static void RunGUI()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        window = new MainWindow();
        Application.Run(window);
    }

    public static void SetState(GameState state)
    {
        window.State = state;
    }
}

И скрипт на Python:

import clr
clr.AddReferenceToFile("TG.Model.dll")
clr.AddReferenceToFile("TG.UI.dll")
from TG.Model import GameState
from TG.UI import Program
import thread
import time


def main():
    print "Hello!"
    state = GameState()
    print state.CharacterName
    print dir(Program)
    thread.start_new_thread(Program.RunGUI, ())
    #Program.RunGUI()
    time.sleep(2)
    Program.SetState(state)
    raw_input()


if __name__ == "__main__":
    main()
3
Gavin H 4 Авг 2010 в 07:23

3 ответа

Лучший ответ

Поместите все после вызова Program.RunGUI() в обработчик событий.

C #:

public static void RunGUI(EventHandler onLoad)
{   
    ...

    window = new MainWindow();
    window.Load += onLoad;
    Application.Run(window);
    window.Load -= onLoad; //removes handler in case RunGUI() is called again
}

Python :

def onload(sender, args):
    time.sleep(2)
    Program.SetState(state)
    raw_input()  

def main():
    ...
    Program.RunGUI(onload)
3
Mark Cidade 5 Авг 2010 в 09:55

Если вы хотите изменить GUI из потока, отличного от потока GUI, вы должны использовать метод Invoke.

0
xport 5 Авг 2010 в 09:59

Элементы управления имеют сходство с потоками и доступны только потоку, который их создал. Есть объект BackgroundWorker, который довольно хорошо обрабатывает передачу данных между потоками.

1
Marco 4 Авг 2010 в 04:37