异步方法返回类型?

时间:2014-03-12 05:08:11

标签: c#

这是我试图使用的脚本(使用CodeDomProvider进行编译和运行)。

AddText("Testing. Press yes to continue.");
var answer = SendYesNo();

if (answer)
{
    AddText("Good.");
    SendOk();
} 
else
{
    AddText("Not good.");
    SendOk();
}

现在。我希望SendYesNo使用AutoResetEvent,因此它会暂停脚本执行,直到给出响应。设置响应后,还会设置自动重置事件,因此会继续执行并返回响应。例如,到目前为止我所拥有的:

public bool SendYesNo()
    {
        this.waitHandle = new AutoResetEvent(false);
        this.waitHandle.WaitOne();

        return this.Selection;
    }

要设置选择,我使用:

public void SetSelection(bool selection)
    {
        this.Selection = selection;
        this.waitHandle.Set();
    }

然而,它不起作用(一旦我设置响应没有任何反应),并且整个程序被卡住了。什么都没有。为什么?我想我必须使用异步,但我不知道如何。另外,我应该为此使用自定义EventHandler吗?

感谢。

2 个答案:

答案 0 :(得分:0)

如果我理解,那么你需要这样的东西。

private Task<bool> SendYesNo()
{
    if (Yes)
    {
        return true;
    }
    else
    {
        return false;
    }
}

然后

AddText("Testing. Press yes to continue.");
var answer = await SendYesNo();

if (answer)
{
    AddText("Good.");
    SendOk();
} 
else
{
    AddText("Not good.");
    SendOk();
}

答案 1 :(得分:0)

这实际上比我想象的要简单得多。该框架提供了TaskCompletionSource<T>类型,可以满足您的需求。

class NpcScript {

    TaskCompletionSource<bool> response = new TaskCompletionSource<bool> ();

    public void SetResponse(bool value) {
        response.SetResult (value);
    }

    async Task<bool> SendYesNo() {
        return await response.Task;
    }


    public async Task Perform() {
        AddText("Testing. Press yes to continue.");
        var answer = await SendYesNo();

        if (answer)
        {
            AddText("Good.");
            SendOk();
        } 
        else
        {
            AddText("Not good.");
            SendOk();
        }
    }
}

编辑:

您也应该通过await从某个异步上下文中调用Perform。例如,假设我创建了一个处理Perform的任务,以及另一个等待某些用户输入的任务,我可以启动这两个任务,但等待它们全部完成,然后继续在线程中执行。

var script = new NpcScript();

var taskPerform = new Task(async () => {
    await script.Perform();
});
taskPerform.Start();

var taskInput = new Task(() =>
    //get user input here
    script.SetResponse (inp);
});
taskInput.Start();

Task.WaitAll(new Task[] { taskPerform, taskInput });