【问题标题】:Cancel AsyncOperation after some time WinRT一段时间后取消 AsyncOperation WinRT
【发布时间】:2015-09-03 23:41:32
【问题描述】:

我正在尝试使用 WebView 中的 Skulpt 执行 Python 脚本。如果python脚本包含一个无限循环应用程序没有响应。

从 C# 执行 Python 脚本

await webView.InvokeScriptAsync("evalPy", new string[1] { script });

在 JavaScript 中:

function evalPy(script) {
    try {
        var result = Sk.importMainWithBody("<stdin>", false, script);
        return Sk.builtins.repr(result).v;
    } catch (err) {

    }
}

InvokeScriptAsyncasync 操作,随时可能有某种方式取消它。

一段时间后我第一次尝试停止 java 脚本:

var task = webView.InvokeScriptAsync("evalPy", new string[1] { script }).AsTask<string>();
task.Wait(2000);
task.AsAsyncOperation<string>().Cancel();

第二次尝试:

var op = webView.InvokeScriptAsync("evalPy", new string[1] { script });
new Task(async () =>
{
    await Task.Delay(2000);
    op.Cancel();
    op.Close();
}).Start();

也尝试在 JavaScript 中设置超时

function evalPy(script) {
    try {
        var result = Sk.importMainWithBody("<stdin>", false, script);
        setTimeout(function () { throw "Times-out"; }, 2000);

        return Sk.builtins.repr(result).v;
    } catch (err) {
    }
}

CodeSkulptor.org 也在使用 Skulpt 在 Web 浏览器中执行 Python 脚本,并在一段时间后停止执行 Python 脚本。

【问题讨论】:

  • 当你await时,该方法在执行完成之前不会返回到JavaScript。因此,无限循环将永远不会返回。当您等待两秒钟然后取消时会发生什么?
  • 当我等待两秒钟然后取消时,无限循环继续。调试器将任务状态显示为已取消,但应用没有响应
  • python 进程将继续执行,但您的方法调用应该返回。你在方法调用中还做了什么吗?
  • Yes python 脚本继续执行,但方法调用返回。不,我在方法调用中没有做任何其他事情。
  • 如何创建两个任务,一个是简单的Task.Delay,另一个是有问题的脚本。然后使用Task.WaitAny。最后,如果任务还在运行,取消它并继续。

标签: c# windows-runtime async-await


【解决方案1】:

我刚刚从 Codecademy 的 html 课程中爬出来,并不太了解细节,但是 javascript 是一种单线程语言,我听说您需要一个 web worker 来实现多线程。

importScripts('./skulpt.js');
importScripts('./skulpt.min.js');
importScripts('./skulpt-stdlib.js');

// file level scope code gets executed when loaded


// Executed when the function postMessage on
//the worker object is called.
// onmessage must be global
onmessage = function(e){
  var out = [];
  try{
    Sk.configure({output:function (t){out.push(t);}});
    Sk.importMainWithBody("<stdin>",false,e.data);
  }catch(e){out.push(e.toString());}
  postMessage(out.join(''));
}

主页脚本(未测试):

var skulptWorker = new Worker('SkulptWorker.js');
skulptWorker.onmessage = function(e){
  //Writing skulpt output to console
  console.log(e.data);
  running = false;
}
var running = true;
skulptWorker.postMessage('print(\'hello world\')');
running = true;
skulptWorker.postMessage('while True:\n    print(\'hello world\')');


setTimeout(function(){
    if(running) skulptWorker.terminate();},5000);

但是有一个缺点,当我在 python 代码中使用 input() 时,skulpt 会抛出一个错误,它无法找到窗口对象,因为它位于工作线程中,我还没有解决方案。

附言 一些测试显示下面的代码冻结了主线程(垃圾邮件 postMessage 是个坏主意):

SkulptWorker.js:

importScripts('./skulpt.js');
importScripts('./skulpt.min.js');
importScripts('./skulpt-stdlib.js');

// file level scope code gets executed when loaded


// Executed when the function postMessage on
//the worker object is called.
// onmessage must be global
onmessage = function(e){
  try{
    Sk.configure({output:function (t){postMessage(t);}});
    Sk.importMainWithBody("<stdin>",false,e.data);
  }catch(e){postMessage(e.toString());}
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多