【问题标题】:ContinueWith as an alternative to the await operatorContinueWith 作为 await 运算符的替代品
【发布时间】:2014-08-09 16:50:21
【问题描述】:

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

但是,我遇到了一个问题。目前,我有一个返回Task<bool>asynchronous 方法。它使用TaskCompletionSource 对象并返回Result。这样,我可以暂停脚本的执行,因为它会等到设置了TaskCompletionSource 对象的Result,然后才返回这个Result

现在,有了 Lua,情况就不同了。我显然不能使用 awaitoperator,因为它是 C# 5.0 的语法,你不能在 Lua 中使用它。所以这就是为什么我要问是否有解决方法。我希望能够获得与我的旧代码(发布在这篇文章下方)相同的结果,而不必使用 awaitoperator。有人告诉我,我可以用Task.ContinueWith 做到这一点,但我对此并不熟悉,网上的例子也很枯燥。如果有人可以向我展示我的代码示例,那就太好了。

这是我的方法:

public async Task<bool> ReturnResult()
{
     this.Response = new TaskCompletionSource<bool>();

     return await this.Response.Task;
}

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

var result = await ReturnResult();

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

基本上,如果您仍然无法理解我想要实现的目标 - 一种停止执行的方法,直到代码的另一部分设置响应为止。但是,它必须是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

【问题讨论】:

  • 你能在你的 Lua 脚本中使用TaskContinueWith 吗?另外,您能否添加设置结果的代码的另一部分?
  • @YuvalItzchakov 不,但我可以注册一个涉及那些在我的 Lua 脚本中使用的方法。 Lua 脚本不能涉及 C# 语法。
  • 你为什么要使用异步方法?你为什么不直接返回this.Response.Task?等待它没有帮助。老实说,你的问题还真不清楚……
  • 我有点困惑你为什么要使用TaskCompletionSource
  • @YuvalItzchakov 因为我真的不熟悉任务。我只想能够在不停止主线程的情况下停止脚本的执行,然后返回响应(仅在我的代码的另一部分设置后)。如果我不使用 await 运算符 - 代码将继续运行。

标签: c# asynchronous lua task


【解决方案1】:

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

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

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

对于生产代码,您可能需要检查任务是否出错等。ContinueWith 的重载允许您指定在哪些情况下要运行延续(仅在成功时,仅在错误时等),您可以添加多个延续。但要让您继续前进,以上内容可能已经足够了。

【讨论】:

    猜你喜欢
    • 2018-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-27
    • 2012-09-26
    • 2012-08-19
    • 2010-10-16
    相关资源
    最近更新 更多