ContinueWith作为await操作符的替代



我的应用程序使用脚本。到目前为止,我使用c#编写脚本,并使用CodeDomProvider编译它们。然而,我一直在考虑使用NLua分支(LuaInterface的分支)切换到Lua,因为它更容易编写脚本,加上我熟悉语法。

然而,我正面临一个问题。目前,我有一个返回Task<bool>asynchronous方法。它使用TaskCompletionSource对象并返回Result。这样,我就可以停止脚本的执行,因为它要等到设置了TaskCompletionSource对象的Result,然后才返回这个Result

现在,在Lua中-它是不同的。我显然不能使用await运算符,因为它是c# 5.0的语法,你不能在Lua中使用它。这就是为什么我问是否有解决这个问题的方法。我希望能够达到与我的旧代码(这是张贴在这篇文章下)相同的结果,而不必使用await运算符。有人告诉我,我可以用Task.ContinueWith做到这一点,但我不熟悉这个,网上的例子很无聊。如果有人能用我的代码给我举个例子,那就太好了。

这是我的方法:
public async Task<bool> ReturnResult()
{
     this.Response = new TaskCompletionSource<bool>();
     return await this.Response.Task;
}

下面是我在脚本中使用它的方式:

var result = await ReturnResult();

TaskCompletionSource对象的Result由我的另一部分代码设置。

基本上,如果你仍然不能理解我想要实现什么——一个方法,它停止执行,直到另一部分代码设置了响应。然而,它必须是asynchronous,因为我不希望我的主线程卡住。

EDIT:尝试JonSkeet的建议和代码只是运行没有停止。下面是完整的Script类。

public class Script
{
    private Lua Lua { get; set; }
    private TaskCompletionSource<bool> Response { get; set; }
    public Script()
    {
        this.Lua = new Lua();
    }
    public void Run()
    {
        this.Lua.RegisterFunction("log", this, typeof(Script).GetMethod("Log"));
        this.Lua.RegisterFunction("returnResult", this, typeof(Script).GetMethod("ReturnResult"));
        this.Lua.DoFile(@"C:test.lua");
    }
    public void SetResponse(bool response)
    {
        this.Response.SetResult(response);
    }
    public Task<bool> ReturnResult()
    {
        this.Response = new TaskCompletionSource<bool>();
        return this.Response.Task;
    }
    public void Log(string text)
    {
        MessageBox.Show(text);
    }
}

下面是Form1的代码:

 public partial class Form1 : Form
{
    private Script Script { get; set; }
    public Form1()
    {
        InitializeComponent();
    }
    private void button1_Click(object sender, EventArgs e)
    {
        this.Script = new Script();
        this.Script.Run();
    }
    private void button2_Click(object sender, EventArgs e)
    {
        this.Script.SetResponse(true);
    }
}

只要按两个按钮,第一个按钮运行,第二个按钮设置响应。

Lua脚本为:

result = returnResult()
log("returned " .. result)

下载NLua

好了,正如您现在声称这与Lua无关,下面是您如何在c#中调用该方法,然后仅在任务完成时记录:

Task<bool> task = ReturnResult();
task.ContinueWith(t => Log("Returned " + t.Result));

这个根本没有停止执行——它只是说当任务从ReturnResult返回完成时,它应该调用日志代码。

对于产品代码,您可能想要检查任务是否出错,等等。ContinueWith的过载允许您指定在哪种情况下要运行延续(仅在成功时,仅在故障时等),并且您可以添加多个延续。但要让你开始,上面的内容可能已经足够了。

最新更新