Member 12440947 Ответов: 1

Как выполнить скрипт движка в отдельной задаче


Я делаю что-то вроде этого, чтобы запустить скрипт python в среде .net (работает нормально):

public partial class MainWindow : Window
{
    private readonly ScriptEngine m_engine;
    private readonly ScriptScope m_scope;

    public MainWindow()
    {
        InitializeComponent();
        m_engine = Python.CreateEngine();
        dynamic scope = m_scope = m_engine.CreateScope();
    }

    public void ExecuteScript()
    {
        try
        {
            m_engine.Execute(textEditor.Text, m_scope);

        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }

    }
}

Было бы неплохо, если бы появилась возможность выполнить инструкцию
m_engine.Execute(textEditor.Text, m_scope);
в фоновом режиме задача не полностью блокировать графический интерфейс приложения.

Что я уже пробовал:

Однако самый простой способ поместить это в такую задачу, как эта:
await Task.Run(() => m_engine.Execute(textEditor.Text, m_scope));
не действовать. Любые идеи о том, как сделать этот пробег?
Спасибо Джо

обновление:
Я получаю следующее сообщение об ошибке: вызывающий поток не может получить доступ к этому объекту, потому что он принадлежит другому потоку.

Обновление 2:
Я понял, что мне нужно поместить Execute между вызовом диспетчера:
await Task.Run(() => this.Dispatcher.Invoke(() => m_engine.Execute(textEditor.Text, m_scope)));; 

Это работает до сих пор, но основной поток с графическим интерфейсом все еще блокируется, пока выполняется скрипт. Что нужно сделать, чтобы поток работал в фоновом режиме и графический интерфейс все еще был доступен?

Обновление 3:

Это мои методы:
private void Run(object sender, RoutedEventArgs e)
{            
      ExecuteScriptAsync(textEditor.Text);
}

private async void ExecuteScriptAsync(string script)
{
    await Task.Run(() => m_engine.Execute(script, m_scope)); 
}           

Когда я просто использую
await Task.Run(() => m_engine.Execute(script, m_scope));
без диспетчера я все еще получаю "вызывающий поток не может получить доступ к этому объекту, потому что им владеет другой поток" (даже при использовании переменной вместо Textbox.Text)
private async void ExecuteScriptAsync(string script)
{
  await Task.Run(() => this.Dispatcher.Invoke(() => m_engine.Execute(script, m_scope).ConfigureAwait(true))); ;
            
}
работает без "вызывающий поток не может получить доступ к этому объекту, потому что он принадлежит другому потоку". Однако пользовательский интерфейс блокируется до тех пор, пока работает скрипт. Вопрос в том, как запустить фоновую задачу, не блокируя вызывающую задачу пользовательского интерфейса.

CHill60

"не работает" не является полезным описанием вашей проблемы. Что происходит/не происходит?

1 Ответов

Рейтинг:
0

Richard Deeming

Цитата:
Вызывающий поток не может получить доступ к этому объекту, поскольку он принадлежит другому потоку.
Вы пытаетесь получить доступ к элементу управления пользовательского интерфейса (textEditor) из фонового потока.

Когда вы вводите Dispatcher вызов, вы толкаете выполнение обратно в поток пользовательского интерфейса.

Вместо этого используйте переменную для передачи данных в фоновый поток:
string scriptToExecute = textEditor.Text;
await Task.Run(() => m_engine.Execute(scriptToExecute, m_scope));