【问题标题】:Is there any way to know if a method is running being awaited from within the method?有什么方法可以知道方法中是否正在等待正在运行的方法?
【发布时间】:2021-01-06 11:36:51
【问题描述】:

我是一名大学生,但由于我喜欢编程,因此我尝试创建一个对我有用的代码库(类似于代码库)。

在此过程中,我开始设计/编写一个异步方法,该方法将用于联锁变量。我的目标是在等待此方法(同步运行)和未等待时产生不同的结果。

一个例子如下:


private int _lock;

public async Task<bool> Lock()
{
    if (method_is_not_being_awaited)
        return Interlocked.Exchange(ref _lock, 1) == 0;

    while (0 != Interlocked.Exchange(ref _lock, 1)) {}
    return true;

}

有什么办法可以达到这样的效果吗?如果是,怎么做?

ps:我知道我可以制作两种不同的方法 bool lock()async Task&lt;bool&gt; lockAsync() 但是,这不是我要求的

【问题讨论】:

  • 听起来你错过了等待如何工作的概念。 await 不会导致方法同步运行,它会导致调用方法的其余部分被链接到返回的任务上。这是一个完全不同的概念。
  • 另外,您希望该方法如何将返回的任务分配给一个变量,然后等待该变量?
  • 是的,我完全明白你想说什么。我“试图做的”肯定不是异步函数的预期用例。只是我试图重新利用它的功能。对于某些人来说,将相同的方法用于两件不同的事情会令人困惑,但对我来说效果很好。所以,出于好奇和兴趣,我决定问问^_^
  • 请注意,正如@user1937198 所暗示的,即使您可以分析代码:var lockTask=Lock(); if (userInput==true) await lockTaskl;,也无法知道方法调用的结果是否曾经被等待。这接近termination/halting problems CS 课程可能涵盖 0 考虑采取一...
  • 这也是正确的,但是使用async void 而不是async Task 方法会如何解决这个问题?

标签: c# .net .net-core async-await


【解决方案1】:

不,不可能做你想做的,因为方法必须返回值,然后才能对结果(包括await)执行任何操作。它并非特定于 async 方法,而是所有代码在 C#(以及几乎任何其他语言)中的行为方式。

另一方面,很容易做一些非常接近你所要求的事情——只要尝试await方法的结果就同步返回值:await本质上只是调用GetAwaiter在结果上,你可以连接它来改变你的方法的状态。

请注意,如果方法一直处于等待状态,您将无法真正知道该怎么做 - 因此,虽然您可以在调用 await 时采取行动,但您实际上无法提前知道是否应该开始异步处理。所以你能做到的最好的就是在同步部分什么都不做,无论如何开始异步处理并在调用await时立即返回结果(中止/忽略方法的异步部分)。

可以在https://www.codeproject.com/Articles/5274659/How-to-Use-the-Csharp-Await-Keyword-On-Anythinghttps://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/task-asynchronous-programming-model 中找到可用作结果的实现类的详细信息。

下面的骨架代码显示了如何实现除非调用 await 否则什么都不做的方法:

class MyTask
{
   public MyAwaitable GetAwaiter()
   {
     return new MyAwaitable();
   }
}

class MyAwaitable : INotifyCompletion
{
   public bool IsCompleted 
   {  
       get { return true; }
   }
   
   public int GetResult()
   {
      return 42; // this is our "result" from method.
   }
   
   public void OnCompleted (Action continuation)
   {
    // just run instantly - no need to save callback as this one is 
    // always "completed"
     continuation(); 
   }
}

MyTask F()
{
   // if your really want you can start async operation here
   // and somehow wire up MyAwaitable.IsComplete to terminate/abandon
   // asynchronous part.

  return new MyTask();
}

【讨论】:

  • 这个“把戏”很有意思!非常感谢您分享您的知识!
猜你喜欢
  • 2019-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-08
  • 1970-01-01
  • 2010-10-11
相关资源
最近更新 更多