如何手动实现等待?

时间:2016-02-23 09:30:16

标签: c# multithreading locking async-await task

作为一个例子,假设我们有这个:

public class MyClass
{    
    public async Task<bool?> MySynchronousNonBlockingFunction()
    {
        await here ...

        return MyDialogResult;
    }      
}

并且来电者必须按以下方式调用我的功能:

public async void Button_Click()
{
    var instance = new MyClass();

    var result = await instance.MySynchronousNonBlockingFunction(); 

    if (result == true)
    {
        some work ...
    }
}

但是使用Task作为等待,迫使你制作MySynchronousNonBlockingFunction()函数async。作为副作用,您必须仅在MyClass.MySynchronousNonBlockingFunction()空格内调用async才能按预期工作。

我认为这对来电者来说不太好。因为应用程序开发团队中的懒惰开发人员可能会在没有MySynchronousNonBlockingFunction()的情况下调用await,然后应用程序将无法正常运行。我想在内部处理我的代码中的async操作而不是调用者。防止这种发展错误。与此相同:

public void Button_Click()
{
    var instance = new MyClass();

    var result = instance.MySynchronousNonBlockingFunction();

    if (result == true)
    {
        some work ...
    }
}

实际上,我不想通过等待也不要实际暂停线程来冻结正在运行的线程,因此它必须可以自由地再次处理其他调用堆栈中的其他工作。我想要的女巫实际上与await执行Task关键字的工作相同。还有其他选择可以使用吗?你在这里实施await行为的解决方案是什么?

我知道在c#中有一些方法lock一个对象是完整的,并强制执行堆栈等待。 (例如,使用MonitorMutex等)。我在c#中找到的所有方法都阻止了正在运行的线程。

但是,我如何实现手动等待?还有另一种方法可以达到这个目的吗?

2 个答案:

答案 0 :(得分:1)

  

实际上,我希望暂停ui线程继续在某个位置执行,然后再次恢复它以便稍后继续执行(从CallStack快照位置)。但我不想冻结或实际上暂停therad因此它必须可以自由地再次处理其他调用堆栈中的其他工作。我想要的女巫实际上与任务执行的await关键字的工作相同。还有其他选择可以使用吗?

await的工作原理并非如此。 await通过返回,然后稍后继续该方法来工作。特别是,调用堆栈捕获。

如果您想要切换线程堆栈,请查看fibers。但是,光纤API没有.NET绑定,如果你尝试使用光纤而不是线程,很可能会破坏很多.NET代码。然后是光纤是否实际上可以成为UI元素的STA上下文的整个问题;我真的不确定那一个。简而言之,这里是龙。

  

你的解决方案是什么?

嗯,模式对话框 - by definition - 假设阻止其他对话框并运行嵌套的消息循环。

如果您不想要此行为,请改为编写无模式对话框。即,致电Show而不是ShowDialog

答案 1 :(得分:0)

GUI窗口处理程序是消息驱动的状态机。您必须编写反映该代码的代码。这意味着不,你不能只是等待,你不应该尝试。