【问题标题】:How to call an asynchronous (await) method synchronously?如何同步调用异步(await)方法?
【发布时间】:2014-02-04 21:35:38
【问题描述】:

我正在使用 parse.com 提供的 .NET API,

https://parse.com/docs/dotnet_guide#objects-saving

我的代码的 sn-p 如下所示;

public async void UploadCurrentXML()
{
   ...
   var query = ParseObject.GetQuery("RANDOM_TABLE").WhereEqualTo("some_field", "string");
   var count = await query.CountAsync();
   ParseObject temp_A;
   temp_A = await query.FirstAsync();
   ...
   // do lots of stuff
   ...
   await temp_A.SaveAsync();
}

总结;对远程数据库进行查询。根据结果​​,从数据库中获得特定对象(或其引用)。对对象执行多次操作,最后将其保存回数据库。

所有数据库操作都通过 await ParseObject.randomfunction() 进行。是否可以以同步方式调用这些函数?或者至少等到操作返回而不继续?该应用程序专为维护目的而设计,运行时间不是问题。

我问这个是因为就目前情况而言,我收到一个错误提示

正在进行的计数操作数已达到限制。

我试过了,

var count = await query.CountAsync().ConfigureAwait(false);

在所有的 await 调用中,但这无济于事 - 代码仍在异步运行。

var count = query.CountAsync().Result;

导致应用程序卡住 - 可以肯定我遇到了死锁。

经过一番搜索,我想到了这个问题,

How would I run an async Task<T> method synchronously?

但我不明白它如何适用于我的案例,因为我无法访问 ParseObject 的源代码。帮助? (我正在使用 .NET 4.5)

【问题讨论】:

  • 为什么不使用您正在使用的方法的同步版本?例如Count(), First()?
  • 遗憾的是,它们不存在。否则我会尝试的。 :(
  • query是什么类型?
  • 新任务(UploadCurrentXML).RunSynchronously();
  • @usr:最好的资源是this blog post,它(简要)涵盖了所有方法,并指出没有通用的解决方案。

标签: c# .net asynchronous parse-platform


【解决方案1】:

我建议您始终使用异步编程。如果您遇到某种资源问题(即,不允许在单个数据库上进行多个查询),那么您应该构建您的代码,以免发生这种情况(例如,在操作进行时禁用 UI 按钮)。或者,如果必须,您可以使用 SemaphoreSlim 来限制您的 async 代码:

private readonly SemaphoreSlim _mutex = new SemaphoreSlim(1);
public async Task UploadCurrentXMLAsync()
{
  await _mutex.WaitAsync();
  try
  {
    ...
    var query = ParseObject.GetQuery("RANDOM_TABLE").WhereEqualTo("some_field",  "string");
    var count = await query.CountAsync();
    ParseObject temp_A;
    temp_A = await query.FirstAsync();
    ...
    // do lots of stuff
    ...
    await temp_A.SaveAsync();
  }
  finally
  {
    _mutex.Release();
  }
}

但如果你真的,真的想要同步阻塞,你可以这样做:

public async Task UploadCurrentXMLAsync();

Task.Run(() => UploadCurrentXMLAsync()).Wait();

再一次,我不能推荐最后一个“解决方案”,它更像是一个 hack,而不是一个适当的解决方案。

【讨论】:

  • 哇。我已经看到您对其他答案的回复,但从没想过您也会帮助我。谢谢! “SemaphoreSlim”的概念对我来说是新的。明天我回去工作时会尝试一下并报告。关于您的第二个“hack”,是否可以将其与“await query.CountAsync()”一起使用并返回一个值?
  • 是的,hack 使用返回值,即var count = Task.Run(() =&gt; query.CountAsync()).Result
  • 从概念上讲,我仍然对整个并行编程感到迷茫。但这是我需要研究的个人问题。此答案中的技巧帮助解决了我在工作中遇到的直接问题,因此我将其标记为答案。 (对于那些关心的人,我的应用程序需要很长时间才能运行,但就其目的而言,这是可以接受的)
  • 异步 != 并行。您可能会发现我的async intro 很有帮助。
【解决方案2】:

如果api方法返回异步任务,可以获取awaiter并同步获取结果

    api.DoWorkAsync().GetAwaiter().GetResult();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-13
    • 1970-01-01
    • 1970-01-01
    • 2020-12-19
    • 2017-09-23
    • 1970-01-01
    相关资源
    最近更新 更多