gpt4 book ai didi

c# - IronPython 作为 C# WPF VS 2015 的脚本语言

转载 作者:太空宇宙 更新时间:2023-11-03 12:54:16 25 4
gpt4 key购买 nike

我遇到了一些麻烦,希望你能帮忙解决!我一直在尝试在 sleep(500) 步骤中在 while 循环中更新此 grid.Width 参数。但是,当我在我的程序上点击运行脚本时,整个 GUI 都停止了。我已经尝试在不同的线程上运行脚本并使用 BackgroundWorker,但在脚本完成之前,它们仍然以两种方式阻止我的应用程序 GUI。你能看看下面的代码吗?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using System.IO;
using System.Threading;
using IronPython.Hosting;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;

namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
string script;
ScriptEngine engine;
ScriptScope scope;
Thread threadScript;

public MainWindow()
{
InitializeComponent();

engine = Python.CreateEngine();
scope = engine.CreateScope();
string variableName = "isto";
object gridMier = gridScript;
scope.SetVariable(variableName, gridMier);
}

public void rodarScript()
{
this.Dispatcher.Invoke((Action)(() =>
{
try
{
//PARTE PARA ADICIONAR BIBLIOTECAS BASICAS PARA DESENVOLVIMENTO COM OS SCRIPTS
script = @"#Reference the WPF assemblies
import clr
clr.AddReferenceByName(""PresentationFramework, Version = 3.0.0.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35"")
clr.AddReferenceByName(""PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"")
import System.Windows
def getMyObject():
return isto

objeto = getMyObject()

#Atalhos de referencias para adicionar
Thickness = System.Windows.Thickness
from System.Threading.Thread import Sleep
Debug = System.Diagnostics.Debug";

script = script + "\n" + textBoxScript.Text;
var source = engine.CreateScriptSourceFromString(script, SourceCodeKind.Statements);
//var compiled = source.Compile();
//var result = compiled.Execute(scope);
source.Execute(scope);
}
catch (Exception qualquerExcecaoEncontrada)
{
MessageBox.Show(qualquerExcecaoEncontrada.ToString(), "Scripting Test do Mier", MessageBoxButton.OK);
}
}));
}

private void buttonScript_Click(object sender, RoutedEventArgs e)
{
threadScript = new Thread(rodarScript);
threadScript.Start();
}
}
}

IronPython 中的代码示例 (textBoxScript.Text)

for num in range(1,100):
objeto.Width = objeto.Width + 1
Sleep(500)

这个在线程上运行的简单代码会阻塞我的整个 GUI 50 秒。任何帮助将不胜感激!

谢谢,卢卡斯。

最佳答案

创建一个单独的线程,然后将完整的内容放入 Dispatcher.Invoke 是没有意义的。因为您随后再次与 ui 线程同步(咆哮时间)。您应该只调用那些需要的东西(UI 访问)。首先从 rodarScript 中删除它,只将它用于 script = script + "\n"+ textBoxScript.Text;:

    public void rodarScript()
{
try
{
//PARTE PARA ADICIONAR BIBLIOTECAS BASICAS PARA DESENVOLVIMENTO COM OS SCRIPTS
script = @"#...";

this.Dispatcher.Invoke((Action)(() =>
{
script = script + "\n" + textBoxScript.Text;
}));

var source = engine.CreateScriptSourceFromString(script, SourceCodeKind.Statements);
//var compiled = source.Compile();
//var result = compiled.Execute(scope);
source.Execute(scope);
}
catch (Exception qualquerExcecaoEncontrada)
{
MessageBox.Show(qualquerExcecaoEncontrada.ToString(), "Scripting Test do Mier", MessageBoxButton.OK);
}
}

(已删除 IP 代码)。

然后添加一些简单的方法,它接受 PythonFunction 的实例并将其添加为变量,如下所示:

public void ExecuteInUI(object obj)
{
this.Dispatcher.BeginInvoke((Action)(() =>
{
var op = engine.CreateOperations(scope);
op.Invoke(obj);
}));
}

添加为变量:

scope.SetVariable("execute_in_ui", new Action<object>(ExecuteInUI));

然后你必须稍微修改一下你的 Python 代码,因为你只想在访问 ui 时使用 BeginInvoke:

def inc_width():
objeto.Width = objeto.Width + 1

for num in range(1,100):
execute_in_ui(inc_width)
Sleep(500)

所以我们将 inc_width 的函数信息传递给 c# 并从那里在 ExecuteInUI 中执行它。那么完整的代码将如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using System.IO;
using System.Threading;
using IronPython.Hosting;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;

namespace AsyncIronPython
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
string script;
ScriptEngine engine;
ScriptScope scope;
Thread threadScript;

public MainWindow()
{
InitializeComponent();

engine = Python.CreateEngine();
scope = engine.CreateScope();
string variableName = "isto";
object gridMier = gridScript;
scope.SetVariable(variableName, gridMier);
scope.SetVariable("execute_in_ui", new Action<object>(ExecuteInUI));
}

public void ExecuteInUI(object obj)
{
this.Dispatcher.BeginInvoke((Action)(() =>
{
var op = engine.CreateOperations(scope);
op.Invoke(obj);
}));
}

public void rodarScript()
{
try
{
//PARTE PARA ADICIONAR BIBLIOTECAS BASICAS PARA DESENVOLVIMENTO COM OS SCRIPTS
script = @"#Reference the WPF assemblies
import clr
clr.AddReferenceByName(""PresentationFramework, Version = 3.0.0.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35"")
clr.AddReferenceByName(""PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"")
import System.Windows
def getMyObject():
return isto

objeto = getMyObject()

#Atalhos de referencias para adicionar
Thickness = System.Windows.Thickness
from System.Threading.Thread import Sleep
Debug = System.Diagnostics.Debug";

this.Dispatcher.Invoke((Action)(() =>
{
script = script + "\n" + textBoxScript.Text;
}));

var source = engine.CreateScriptSourceFromString(script, SourceCodeKind.Statements);
//var compiled = source.Compile();
//var result = compiled.Execute(scope);
source.Execute(scope);
}
catch (Exception qualquerExcecaoEncontrada)
{
MessageBox.Show(qualquerExcecaoEncontrada.ToString(), "Scripting Test do Mier", MessageBoxButton.OK);
}
}

private void buttonScript_Click(object sender, RoutedEventArgs e)
{
threadScript = new Thread(rodarScript);
threadScript.Start();
}
}
}

XAML:

<Window x:Class="AsyncIronPython.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:AsyncIronPython"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="gridScript">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>

<TextBox x:Name="textBoxScript" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="3" AcceptsReturn="True" AcceptsTab="True" />
<Button x:Name="buttonScript" Click="buttonScript_Click" VerticalAlignment="Center" HorizontalAlignment="Stretch" Content="Execute" Grid.Row="1" Margin="3" />

</Grid>
</Window>

希望这对您有所帮助。

关于c# - IronPython 作为 C# WPF VS 2015 的脚本语言,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34502691/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com