Python中IronPython的UI线程如何调用?

在 IronPython 想把 UI 线程和主线程分开,避免被卡死 但是敲好代码后发现代码在 UI 下不起作用?

import wpf
from System.Windows import Application, Window
from threading import Thread
import time

class TiebaClientTools(Window):

def __init__(self):
    wpf.LoadComponent(self, 'TiebaClientTools.xaml')


    

def Button_Click(self, sender, e):
    def set_text(num):
        time.sleep(num)
        self.textbox.Text = "new text"
    t = Thread(target=set_text, args=(3,))
    t.start()

if name == ‘main’: Application().Run(TiebaClientTools())


Python中IronPython的UI线程如何调用?

2 回复

在IronPython中处理UI线程调用,核心是使用Dispatcher。WPF和WinForms的调用方式不同,我分别给你示例。

WPF应用示例:

import clr
clr.AddReference('PresentationFramework')
clr.AddReference('PresentationCore')

from System.Windows import Application, Window
from System.Windows.Threading import Dispatcher
import System

class MainWindow(Window):
    def __init__(self):
        self.Title = "IronPython WPF Demo"
        self.Width = 400
        self.Height = 300
        
        # 模拟后台线程更新UI
        import threading
        thread = threading.Thread(target=self.update_from_thread)
        thread.Start()

    def update_from_thread(self):
        # 在非UI线程中调用
        self.Dispatcher.Invoke(
            System.Action(lambda: self.Title = "Updated from Thread")
        )

app = Application()
window = MainWindow()
app.Run(window)

WinForms应用示例:

import clr
clr.AddReference('System.Windows.Forms')
clr.AddReference('System.Drawing')

from System.Windows.Forms import Application, Form, Label, Button
from System.Drawing import Point, Size
import System

class MainForm(Form):
    def __init__(self):
        self.Text = "IronPython WinForms Demo"
        self.Size = Size(400, 300)
        
        self.label = Label()
        self.label.Text = "Initial Text"
        self.label.Location = Point(50, 50)
        self.Controls.Add(self.label)
        
        btn = Button()
        btn.Text = "Update from Thread"
        btn.Location = Point(50, 100)
        btn.Click += self.on_button_click
        self.Controls.Add(btn)
    
    def on_button_click(self, sender, args):
        import threading
        threading.Thread(target=self.update_label).Start()
    
    def update_label(self):
        if self.InvokeRequired:
            self.Invoke(System.Action(self.update_label))
            return
        self.label.Text = "Updated from Thread"

Application.Run(MainForm())

关键点:

  1. WPFDispatcher.Invoke()BeginInvoke()
  2. WinFormsControl.Invoke()BeginInvoke(),配合InvokeRequired检查
  3. 两种方式都需要将更新操作包装成委托(如System.Action

简单建议: 记住InvokeRequired检查能避免跨线程异常。


首先,ui 线程还是在主线程下的,而且我记得操作系统对主线程启动为 ui 线程是有特殊处理的,你这样是没办法把 ui 线程放到其他线程的

回到顶部