我有一个公共异步无效Foo()方法,我想从同步方法调用。到目前为止,我从MSDN文档中看到的都是通过异步方法调用异步方法,但我的整个程序并不是用异步方法构建的。

这可能吗?

下面是一个从异步方法调用这些方法的例子: 演练:使用Async和Await访问Web (c#和Visual Basic)

现在我正在研究从sync方法调用这些async方法。


当前回答

public async Task<string> StartMyTask()
{
    await Foo()
    // code to execute once foo is done
}

static void Main()
{
     var myTask = StartMyTask(); // call your method which will return control once it hits await
     // now you can continue executing code here
     string result = myTask.Result; // wait for the task to complete to continue
     // use result

}

您将‘await’关键字读为“启动这个长时间运行的任务,然后将控制权返回给调用方法”。长时间运行的任务完成后,它将执行后面的代码。await之后的代码类似于过去的CallBack方法。最大的区别是逻辑流没有中断,这使得读写更容易。

其他回答

对于任何还在关注这个问题的人…

在微软。visualstudio。services。webapi中有一个叫TaskExtensions的类。在这个类中,你会看到静态扩展方法task . syncresult(),它会完全阻塞线程,直到任务返回。

在内部,它调用Task . getawaiter ().GetResult(),这是非常简单的,但是它重载工作在任何异步方法,返回Task, Task<T>或Task<HttpResponseMessage>…语法糖,宝贝…爸爸爱吃甜食。

getresult()是在阻塞上下文中执行异步代码的ms官方方式。似乎在我的用例中工作得很好。

var result = Task.Run(async () => await configManager.GetConfigurationAsync()).ConfigureAwait(false);

OpenIdConnectConfiguration config = result.GetAwaiter().GetResult();

或者用这个:

var result=result.GetAwaiter().GetResult().AccessToken

我不是100%确定,但我相信这篇博客中描述的技巧在许多情况下都适用:

因此,如果想直接调用这个传播逻辑,可以使用task.GetAwaiter(). getresult()。

现在,您可以使用源生成器使用同步方法生成器库(nuget)创建方法的同步版本。

使用方法如下:

[Zomp.SyncMethodGenerator.CreateSyncVersion]
public async void FooAsync()

它会生成Foo方法,你可以同步调用。

这是最简单的解决办法。我在网上的某个地方看到它,我不记得在哪里了,但我一直在成功地使用它。它不会死锁调用线程。

    void SynchronousFunction()
    {
        Task.Run(Foo).Wait();
    }

    string SynchronousFunctionReturnsString()
    {
        return Task.Run(Foo).Result;
    }

    string SynchronousFunctionReturnsStringWithParam(int id)
    {
        return Task.Run(() => Foo(id)).Result;
    }