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 await
operator 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 await
operator. 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.
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.
See more on this question at Stackoverflow