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

这可能吗?

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

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


当前回答

这些windows异步方法有一个漂亮的小方法叫做AsTask()。您可以使用它让方法作为任务返回本身,以便您可以手动调用Wait()。

例如,在Windows Phone 8 Silverlight应用程序中,您可以执行以下操作:

private void DeleteSynchronous(string path)
{
    StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
    Task t = localFolder.DeleteAsync(StorageDeleteOption.PermanentDelete).AsTask();
    t.Wait();
}

private void FunctionThatNeedsToBeSynchronous()
{
    // Do some work here
    // ....

    // Delete something in storage synchronously
    DeleteSynchronous("pathGoesHere");

    // Do other work here 
    // .....
}

希望这能有所帮助!

其他回答

这些windows异步方法有一个漂亮的小方法叫做AsTask()。您可以使用它让方法作为任务返回本身,以便您可以手动调用Wait()。

例如,在Windows Phone 8 Silverlight应用程序中,您可以执行以下操作:

private void DeleteSynchronous(string path)
{
    StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
    Task t = localFolder.DeleteAsync(StorageDeleteOption.PermanentDelete).AsTask();
    t.Wait();
}

private void FunctionThatNeedsToBeSynchronous()
{
    // Do some work here
    // ....

    // Delete something in storage synchronously
    DeleteSynchronous("pathGoesHere");

    // Do other work here 
    // .....
}

希望这能有所帮助!

在尝试了几个小时不同的方法后,或多或少取得了成功,这就是我最终得到的结果。它在获取结果时不会以死锁结束,它还会获取并抛出原始异常,而不是被包装的异常。

private ReturnType RunSync()
{
  var task = Task.Run(async () => await myMethodAsync(agency));
  if (task.IsFaulted && task.Exception != null)
  {
    throw task.Exception;
  }

  return task.Result;
}

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

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

如果你想运行它同步

MethodAsync().RunSynchronously()

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

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

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

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