ContinueWith as an alternative to the await operator

My application uses scripts. So far, I've used C# for the scripts and compiled them using the CodeDomProvider. However, I've been thinking about switching to Lua using the NLua fork (a fork of the LuaInterface) because it's much easier to write scripts with plus I'm familiar with the syntax.

However, I'm facing a problem. Currently, I have an asynchronous method that returns a Task<bool>. It uses a TaskCompletionSource object and returns it's Result. That way, I can halt the execution of the script because it waits until the Result of the TaskCompletionSource object has been set, and only then returns this Result.

Now, with Lua - it's different. I obviously can't use the awaitoperator because it's a syntax of C# 5.0, and you can't use that in Lua. So that's why I'm asking if there's a workaround for this. I want to be able to achieve the same result as my old code (which is posted beneath this post) without having to use the awaitoperator. I've been told that I can do that with Task.ContinueWith, but I'm unfamiliar with this and the examples online are dull. If anyone can show me an example with my code, it'd be great.

Here's my method:

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

     return await this.Response.Task;
}

Here's the way I'm using it in my scripts:

var result = await ReturnResult();

The Result of the TaskCompletionSource object is set by another part of my code.

Basically, if you still failed to understand what I want to achieve - a method that halts it's execution until a response has been set by another part of the code. However, it has to be asynchronous, because I don't want my main thread to get stuck.

EDIT: Tried JonSkeet's suggestion and the code just runs without halting. Here's the full Script class.

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);
    }
}

Here's the code of 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);
    }
}

Just throw two buttons and use the first one to run, second one to set response.

The Lua script is:

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

Download NLua from here.

Jon Skeet
people
quotationmark

Okay, as you now claim this has nothing to do with Lua, here's how you would call the method in C#, then log only when the task had completed:

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

This does not halt execution at all - it just says that when the task returned from ReturnResult completes, it should call the logging code.

For production code, you would probably want to check whether the task was faulted, etc. There are overloads of ContinueWith which allow you to specify under which circumstances you want to run the continuation (only on success, only on fault etc), and you can add multiple continuations. But to get you going, the above is probably good enough.

people

See more on this question at Stackoverflow