2010-08-04 72 views
3

所以我在Visual Studio中用C#做了一个Winforms GUI,但是对于我正在开发的项目我希望大部分代码都是用Python编写的。我希望有用Python编写的“引擎”(用于可移植性),然后让应用程序接口成为我可以替换的东西。用IronPython控制C#Winforms GUI

我将C#项目编译为.dll,并且能够将类导入IronPython脚本并启动GUI。

问题是运行GUI会停止Python脚本的执行,除非我把它放到单独的线程中。但是,如果我将GUI放入单独的线程并尝试使用原始python线程来更改状态信息,那么我将得到有关从不同于创建它的线程修改控件的异常。

有没有什么好的方法与GUI线程沟通或完成我想要做的事情?

GUI的C#驱动程序:

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

在事件处理程序的调用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) 
+0

这个解决方案看起来像我正在寻找的,但是当我尝试这样做时,onload()函数中的代码没有运行。如果我只是在那里放一个打印语句,例如GUI启动后没有打印出来。任何想法为什么?谢谢你的帮助! – 2010-08-04 03:49:03

+0

我不知道为什么。尝试从python实例化MainWindow类并直接添加事件处理程序 - 这在过去对我很有用。 – 2010-08-04 05:26:27

+0

您也可以分解成C#代码来查看事件处理程序是否确实已注册。 – 2010-08-04 05:28:35

1

控件具有线程关联,并且只能由创建它们的线程访问。 有一个BackgroundWorker对象可以很好地处理线程之间的传递数据。

0

如果要从GUI线程以外的线程修改GUI,则必须使用Invoke方法。