ContinueWith作为await运算符的替代

时间:2014-08-09 07:17:49

标签: c# asynchronous lua task

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

然而,我遇到了一个问题。目前,我有asynchronous方法返回Task<bool>。它使用TaskCompletionSource对象并返回Result。这样,我可以暂停脚本的执行,因为它一直等到Result对象的TaskCompletionSource被设置,然后才返回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();

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

基本上,如果您仍然无法理解我想要实现的目标 - 一种方法会暂停执行,直到代码的另一部分设置了响应为止。但是,它必须是asynchronous,因为我不希望我的主线程卡住。

编辑:尝试了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

1 个答案:

答案 0 :(得分:4)

好的,正如您现在声称这与Lua无关,这里是您如何在C#中调用该方法,然后仅在任务完成时进行记录:

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

完全停止执行 - 只是说当ReturnResult返回的任务完成时,它应该调用日志代码。

对于生产代码,您可能想要检查任务是否出现故障等。ContinueWith存在重载,允许您指定在哪种情况下运行延续(仅在成功时,仅在故障等),你可以添加多个延续。但为了让你继续前进,上述情况可能还不错。